@vitessce/all 3.5.10 → 3.5.12

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.
@@ -10466,6 +10466,7 @@ const CoordinationType$1 = {
10466
10466
  FEATURE_VALUE_COLORMAP: "featureValueColormap",
10467
10467
  FEATURE_VALUE_TRANSFORM: "featureValueTransform",
10468
10468
  FEATURE_VALUE_COLORMAP_RANGE: "featureValueColormapRange",
10469
+ FEATURE_AGGREGATION_STRATEGY: "featureAggregationStrategy",
10469
10470
  OBS_COLOR_ENCODING: "obsColorEncoding",
10470
10471
  SPATIAL_IMAGE_LAYER: "spatialImageLayer",
10471
10472
  SPATIAL_SEGMENTATION_LAYER: "spatialSegmentationLayer",
@@ -10691,6 +10692,7 @@ const COMPONENT_COORDINATION_TYPES = {
10691
10692
  CoordinationType$1.FEATURE_SELECTION,
10692
10693
  CoordinationType$1.FEATURE_VALUE_COLORMAP,
10693
10694
  CoordinationType$1.FEATURE_VALUE_COLORMAP_RANGE,
10695
+ CoordinationType$1.FEATURE_AGGREGATION_STRATEGY,
10694
10696
  CoordinationType$1.OBS_COLOR_ENCODING,
10695
10697
  CoordinationType$1.ADDITIONAL_OBS_SETS,
10696
10698
  CoordinationType$1.TOOLTIPS_VISIBLE,
@@ -10734,6 +10736,7 @@ const COMPONENT_COORDINATION_TYPES = {
10734
10736
  CoordinationType$1.FEATURE_SELECTION,
10735
10737
  CoordinationType$1.FEATURE_VALUE_COLORMAP,
10736
10738
  CoordinationType$1.FEATURE_VALUE_COLORMAP_RANGE,
10739
+ CoordinationType$1.FEATURE_AGGREGATION_STRATEGY,
10737
10740
  CoordinationType$1.OBS_COLOR_ENCODING,
10738
10741
  CoordinationType$1.ADDITIONAL_OBS_SETS,
10739
10742
  CoordinationType$1.TOOLTIPS_VISIBLE,
@@ -10813,10 +10816,12 @@ const COMPONENT_COORDINATION_TYPES = {
10813
10816
  CoordinationType$1.FEATURE_SELECTION,
10814
10817
  CoordinationType$1.FEATURE_VALUE_COLORMAP,
10815
10818
  CoordinationType$1.FEATURE_VALUE_COLORMAP_RANGE,
10819
+ CoordinationType$1.FEATURE_AGGREGATION_STRATEGY,
10816
10820
  CoordinationType$1.OBS_COLOR_ENCODING,
10817
10821
  CoordinationType$1.ADDITIONAL_OBS_SETS,
10818
10822
  CoordinationType$1.MOLECULE_HIGHLIGHT,
10819
- CoordinationType$1.TOOLTIPS_VISIBLE
10823
+ CoordinationType$1.TOOLTIPS_VISIBLE,
10824
+ CoordinationType$1.PHOTOMETRIC_INTERPRETATION
10820
10825
  ],
10821
10826
  [ViewType$1.SPATIAL_BETA]: [
10822
10827
  CoordinationType$1.META_COORDINATION_SCOPES,
@@ -10850,6 +10855,7 @@ const COMPONENT_COORDINATION_TYPES = {
10850
10855
  CoordinationType$1.FEATURE_SELECTION,
10851
10856
  CoordinationType$1.FEATURE_VALUE_COLORMAP,
10852
10857
  CoordinationType$1.FEATURE_VALUE_COLORMAP_RANGE,
10858
+ CoordinationType$1.FEATURE_AGGREGATION_STRATEGY,
10853
10859
  CoordinationType$1.OBS_COLOR_ENCODING,
10854
10860
  CoordinationType$1.ADDITIONAL_OBS_SETS,
10855
10861
  CoordinationType$1.MOLECULE_HIGHLIGHT,
@@ -10888,7 +10894,8 @@ const COMPONENT_COORDINATION_TYPES = {
10888
10894
  CoordinationType$1.LEGEND_VISIBLE,
10889
10895
  CoordinationType$1.SPATIAL_CHANNEL_LABELS_VISIBLE,
10890
10896
  CoordinationType$1.SPATIAL_CHANNEL_LABELS_ORIENTATION,
10891
- CoordinationType$1.SPATIAL_CHANNEL_LABEL_SIZE
10897
+ CoordinationType$1.SPATIAL_CHANNEL_LABEL_SIZE,
10898
+ CoordinationType$1.PHOTOMETRIC_INTERPRETATION
10892
10899
  ],
10893
10900
  [ViewType$1.HEATMAP]: [
10894
10901
  CoordinationType$1.DATASET,
@@ -10963,6 +10970,7 @@ const COMPONENT_COORDINATION_TYPES = {
10963
10970
  CoordinationType$1.FEATURE_SELECTION,
10964
10971
  CoordinationType$1.FEATURE_VALUE_TRANSFORM,
10965
10972
  CoordinationType$1.FEATURE_VALUE_TRANSFORM_COEFFICIENT,
10973
+ CoordinationType$1.FEATURE_AGGREGATION_STRATEGY,
10966
10974
  CoordinationType$1.OBS_SET_SELECTION,
10967
10975
  CoordinationType$1.OBS_SET_FILTER,
10968
10976
  CoordinationType$1.OBS_SET_HIGHLIGHT,
@@ -10978,6 +10986,7 @@ const COMPONENT_COORDINATION_TYPES = {
10978
10986
  CoordinationType$1.FEATURE_TYPE,
10979
10987
  CoordinationType$1.FEATURE_VALUE_TYPE,
10980
10988
  CoordinationType$1.FEATURE_SELECTION,
10989
+ CoordinationType$1.FEATURE_AGGREGATION_STRATEGY,
10981
10990
  CoordinationType$1.ADDITIONAL_OBS_SETS,
10982
10991
  CoordinationType$1.OBS_SET_COLOR,
10983
10992
  CoordinationType$1.OBS_COLOR_ENCODING,
@@ -11001,7 +11010,8 @@ const COMPONENT_COORDINATION_TYPES = {
11001
11010
  CoordinationType$1.SPATIAL_ROTATION_Y,
11002
11011
  CoordinationType$1.SPATIAL_ROTATION_Z,
11003
11012
  CoordinationType$1.SPATIAL_ROTATION_ORBIT,
11004
- CoordinationType$1.SPATIAL_ORBIT_AXIS
11013
+ CoordinationType$1.SPATIAL_ORBIT_AXIS,
11014
+ CoordinationType$1.PHOTOMETRIC_INTERPRETATION
11005
11015
  ],
11006
11016
  [ViewType$1.LAYER_CONTROLLER_BETA]: [
11007
11017
  CoordinationType$1.META_COORDINATION_SCOPES,
@@ -11056,6 +11066,7 @@ const COMPONENT_COORDINATION_TYPES = {
11056
11066
  CoordinationType$1.FEATURE_VALUE_COLORMAP,
11057
11067
  CoordinationType$1.FEATURE_VALUE_COLORMAP_RANGE,
11058
11068
  CoordinationType$1.FEATURE_SELECTION,
11069
+ CoordinationType$1.FEATURE_AGGREGATION_STRATEGY,
11059
11070
  CoordinationType$1.TOOLTIPS_VISIBLE,
11060
11071
  CoordinationType$1.TOOLTIP_CROSSHAIRS_VISIBLE,
11061
11072
  CoordinationType$1.LEGEND_VISIBLE,
@@ -11096,6 +11107,7 @@ const COMPONENT_COORDINATION_TYPES = {
11096
11107
  CoordinationType$1.FEATURE_VALUE_TRANSFORM_COEFFICIENT,
11097
11108
  CoordinationType$1.FEATURE_VALUE_POSITIVITY_THRESHOLD,
11098
11109
  CoordinationType$1.FEATURE_VALUE_COLORMAP,
11110
+ CoordinationType$1.FEATURE_AGGREGATION_STRATEGY,
11099
11111
  CoordinationType$1.OBS_SET_SELECTION,
11100
11112
  CoordinationType$1.OBS_SET_FILTER,
11101
11113
  CoordinationType$1.OBS_SET_HIGHLIGHT,
@@ -11124,6 +11136,7 @@ const COMPONENT_COORDINATION_TYPES = {
11124
11136
  CoordinationType$1.FEATURE_SELECTION,
11125
11137
  CoordinationType$1.FEATURE_VALUE_TRANSFORM,
11126
11138
  CoordinationType$1.FEATURE_VALUE_TRANSFORM_COEFFICIENT,
11139
+ CoordinationType$1.FEATURE_AGGREGATION_STRATEGY,
11127
11140
  CoordinationType$1.OBS_SET_SELECTION,
11128
11141
  CoordinationType$1.OBS_SET_HIGHLIGHT,
11129
11142
  CoordinationType$1.OBS_HIGHLIGHT,
@@ -11228,6 +11241,7 @@ const COMPONENT_COORDINATION_TYPES = {
11228
11241
  CoordinationType$1.OBS_TYPE,
11229
11242
  CoordinationType$1.SAMPLE_TYPE,
11230
11243
  CoordinationType$1.FEATURE_SELECTION,
11244
+ CoordinationType$1.FEATURE_AGGREGATION_STRATEGY,
11231
11245
  CoordinationType$1.SAMPLE_SET_SELECTION,
11232
11246
  CoordinationType$1.SAMPLE_SET_FILTER,
11233
11247
  CoordinationType$1.OBS_SET_SELECTION,
@@ -11601,6 +11615,7 @@ const annDataFeatureSetStats = z.object({
11601
11615
  termColumn: z.string().optional(),
11602
11616
  pValueColumn: z.string(),
11603
11617
  pValueAdjusted: z.boolean().optional(),
11618
+ featureSetLibrary: z.string().optional().describe("Optionally, provide a feature set library name. By default, Reactome_2022."),
11604
11619
  analysisType: z.string().optional().describe("Optionally, provide an analysis_type name. By default, pertpy_hypergeometric.")
11605
11620
  });
11606
11621
  const annDataObsSetStats = z.object({
@@ -11611,7 +11626,6 @@ const annDataObsSetStats = z.object({
11611
11626
  foldChangeColumn: z.string().describe("The log-fold change is then calculated between this expected sample and the expected sample with no active covariates from the intercept section."),
11612
11627
  foldChangeTransformation: z.enum(["log2"]).optional(),
11613
11628
  isCredibleEffectColumn: z.string().describe("Column which annotates effects as being credible or not (boolean)."),
11614
- covariateColumn: z.string().describe("Column which defines the covariate used in the analysis."),
11615
11629
  analysisType: z.string().optional().describe("Optionally, provide an analysis_type name. By default, sccoda_df.")
11616
11630
  });
11617
11631
  const annDataObsLabels = annDataObs;
@@ -53362,7 +53376,7 @@ function getCellColors(params2) {
53362
53376
  }
53363
53377
  return /* @__PURE__ */ new Map();
53364
53378
  }
53365
- function stratifyArrays(sampleEdges, sampleIdToObsIdsMap, sampleSets, sampleSetSelection, obsIndex, mergedCellSets, cellSetSelection, arraysToStratify) {
53379
+ function stratifyArrays(sampleEdges, sampleIdToObsIdsMap, sampleSets, sampleSetSelection, obsIndex, mergedCellSets, cellSetSelection, arraysToStratify, featureAggregationStrategy) {
53366
53380
  const result = new InternMap$1([], JSON.stringify);
53367
53381
  const hasSampleSetSelection = Array.isArray(sampleSetSelection) && sampleSetSelection.length > 0;
53368
53382
  const hasCellSetSelection = Array.isArray(cellSetSelection) && cellSetSelection.length > 0;
@@ -53372,9 +53386,13 @@ function stratifyArrays(sampleEdges, sampleIdToObsIdsMap, sampleSets, sampleSetS
53372
53386
  if (arrKeys.includes("obsIndex") || arrKeys.includes("i")) {
53373
53387
  throw new Error('The keys "obsIndex" and "i" are reserved for internal use.');
53374
53388
  }
53375
- if (Object.values(arraysToStratify).some((arr) => arr.length !== obsIndex.length)) {
53376
- throw new Error("All arrays must have the same length as the obsIndex.");
53377
- }
53389
+ if (Object.entries(arraysToStratify).some(([arrKey, arr]) => {
53390
+ if (arrKey === "featureValue") {
53391
+ return arr.some((a2) => a2.length !== obsIndex.length);
53392
+ }
53393
+ return arr.length !== obsIndex.length;
53394
+ }))
53395
+ ;
53378
53396
  const sampleSetInfo = sampleSets && sampleSetSelection ? treeToObsIdsBySetNames(sampleSets, sampleSetSelection) : null;
53379
53397
  const cellSetInfo = mergedCellSets && cellSetSelection ? treeToObsIdsBySetNames(mergedCellSets, cellSetSelection) : null;
53380
53398
  cellSetKeys.forEach((cellSetKey) => {
@@ -53404,6 +53422,7 @@ function stratifyArrays(sampleEdges, sampleIdToObsIdsMap, sampleSets, sampleSetS
53404
53422
  });
53405
53423
  const sampleIdToSetMap = sampleSets && sampleSetSelection ? treeToSelectedSetMap(sampleSets, sampleSetSelection) : null;
53406
53424
  const cellIdToSetMap = mergedCellSets && cellSetSelection ? treeToSelectedSetMap(mergedCellSets, cellSetSelection) : null;
53425
+ let cellCount = 0;
53407
53426
  for (let i2 = 0; i2 < obsIndex.length; i2 += 1) {
53408
53427
  const obsId = obsIndex[i2];
53409
53428
  const cellSet = (cellIdToSetMap == null ? void 0 : cellIdToSetMap.get(obsId)) || null;
@@ -53414,10 +53433,28 @@ function stratifyArrays(sampleEdges, sampleIdToObsIdsMap, sampleSets, sampleSetS
53414
53433
  }
53415
53434
  const insertionIndex = result.get(cellSet).get(sampleSet).get("i");
53416
53435
  arrKeys.forEach((arrKey) => {
53417
- const value2 = arraysToStratify[arrKey][i2];
53436
+ let value2;
53437
+ if (arrKey === "featureValue") {
53438
+ if (featureAggregationStrategy === "first") {
53439
+ value2 = arraysToStratify[arrKey][0][i2];
53440
+ } else if (featureAggregationStrategy === "last") {
53441
+ value2 = arraysToStratify[arrKey].at(-1)[i2];
53442
+ } else if (typeof featureAggregationStrategy === "number") {
53443
+ const j = featureAggregationStrategy;
53444
+ value2 = arraysToStratify[arrKey][j][i2];
53445
+ } else if (featureAggregationStrategy === "sum" || featureAggregationStrategy === "mean") {
53446
+ value2 = arraysToStratify[arrKey].reduce((a2, h2) => a2 + h2[i2], 0);
53447
+ if (featureAggregationStrategy === "mean") {
53448
+ value2 /= arraysToStratify[arrKey].length;
53449
+ }
53450
+ }
53451
+ } else {
53452
+ value2 = arraysToStratify[arrKey][i2];
53453
+ }
53418
53454
  result.get(cellSet).get(sampleSet).get(arrKey)[insertionIndex] = value2;
53419
53455
  });
53420
53456
  result.get(cellSet).get(sampleSet).set("i", insertionIndex + 1);
53457
+ cellCount += 1;
53421
53458
  }
53422
53459
  cellSetKeys.forEach((cellSetKey) => {
53423
53460
  sampleSetKeys.forEach((sampleSetKey) => {
@@ -53428,7 +53465,7 @@ function stratifyArrays(sampleEdges, sampleIdToObsIdsMap, sampleSets, sampleSetS
53428
53465
  result.get(cellSetKey).get(sampleSetKey).delete("i");
53429
53466
  });
53430
53467
  });
53431
- return result;
53468
+ return [result, cellCount];
53432
53469
  }
53433
53470
  function stratifyExpressionData(sampleEdges, sampleSets, sampleSetSelection, expressionData, obsIndex, mergedCellSets, geneSelection, cellSetSelection, cellSetColor, featureValueTransform, featureValueTransformCoefficient) {
53434
53471
  const result = new InternMap$1([], JSON.stringify);
@@ -53472,12 +53509,38 @@ function stratifyExpressionData(sampleEdges, sampleSets, sampleSetSelection, exp
53472
53509
  }
53473
53510
  return [null, null];
53474
53511
  }
53475
- function aggregateStratifiedExpressionData(stratifiedResult, geneSelection) {
53512
+ function aggregateStratifiedExpressionData(stratifiedResult, geneSelection, featureAggregationStrategy) {
53476
53513
  const result = new InternMap$1([], JSON.stringify);
53477
53514
  Array.from(stratifiedResult.entries()).forEach(([cellSetKey, firstLevelInternMap]) => {
53478
53515
  result.set(cellSetKey, new InternMap$1([], JSON.stringify));
53479
53516
  Array.from(firstLevelInternMap.entries()).forEach(([sampleSetKey, secondLevelInternMap]) => {
53480
- const values3 = secondLevelInternMap.get(geneSelection[0]);
53517
+ let values3;
53518
+ if (featureAggregationStrategy === "first") {
53519
+ values3 = secondLevelInternMap.get(geneSelection[0]);
53520
+ } else if (featureAggregationStrategy === "last") {
53521
+ values3 = secondLevelInternMap.get(geneSelection.at(-1));
53522
+ } else if (typeof featureAggregationStrategy === "number") {
53523
+ const i2 = featureAggregationStrategy;
53524
+ if (i2 >= 0 && i2 < geneSelection.length) {
53525
+ values3 = secondLevelInternMap.get(geneSelection[i2]);
53526
+ } else {
53527
+ throw new Error("Feature index used for featureAggregationStrategy is invalid.");
53528
+ }
53529
+ } else if (featureAggregationStrategy === "sum" || featureAggregationStrategy === "mean") {
53530
+ const subarrays = geneSelection.map((geneId) => secondLevelInternMap.get(geneId));
53531
+ values3 = subarrays.reduce((acc, curr) => acc.map((val, idx) => val + curr[idx]));
53532
+ if (featureAggregationStrategy === "mean") {
53533
+ const N2 = geneSelection.length;
53534
+ values3 = values3.map((val) => val / N2);
53535
+ }
53536
+ } else if (featureAggregationStrategy === "difference") {
53537
+ if (geneSelection.length === 2) {
53538
+ const subarrays = geneSelection.map((geneId) => secondLevelInternMap.get(geneId));
53539
+ values3 = subarrays.reduce((acc, curr) => acc.map((val, idx) => val - curr[idx]));
53540
+ } else {
53541
+ throw new Error("Expected exactly two selected features when featureAggregationStrategy is difference.");
53542
+ }
53543
+ }
53481
53544
  result.get(cellSetKey).set(sampleSetKey, values3);
53482
53545
  });
53483
53546
  });
@@ -175382,8 +175445,15 @@ class SelectionLayer extends CompositeLayer {
175382
175445
  if (!nodePolygonContainsSelectedPolygon && !nodePolygonWithinSelectedPolygon && !nodePolygonOverlapsSelectedPolgyon) {
175383
175446
  return true;
175384
175447
  }
175385
- if (node2.data && booleanPointInPolygon$1(point$a([].slice.call(getObsCoords(node2.data))), selectedPolygon)) {
175386
- pickingInfos.push(node2.data);
175448
+ if (node2.data) {
175449
+ let current2 = node2;
175450
+ while (current2) {
175451
+ const pointCoords = [].slice.call(getObsCoords(current2.data));
175452
+ if (booleanPointInPolygon$1(point$a(pointCoords), selectedPolygon)) {
175453
+ pickingInfos.push(current2.data);
175454
+ }
175455
+ current2 = current2.next;
175456
+ }
175387
175457
  }
175388
175458
  return false;
175389
175459
  });
@@ -177279,16 +177349,16 @@ async function getDecoder(fileDirectory) {
177279
177349
  const Decoder = await importFn();
177280
177350
  return new Decoder(fileDirectory);
177281
177351
  }
177282
- addDecoder([void 0, 1], () => import("./raw-27b6a685.js").then((m2) => m2.default));
177283
- addDecoder(5, () => import("./lzw-8adf7fb3.js").then((m2) => m2.default));
177352
+ addDecoder([void 0, 1], () => import("./raw-1af0a143.js").then((m2) => m2.default));
177353
+ addDecoder(5, () => import("./lzw-615797a2.js").then((m2) => m2.default));
177284
177354
  addDecoder(6, () => {
177285
177355
  throw new Error("old style JPEG compression is not supported.");
177286
177356
  });
177287
- addDecoder(7, () => import("./jpeg-96ca6dfa.js").then((m2) => m2.default));
177288
- addDecoder([8, 32946], () => import("./deflate-d652c9c3.js").then((m2) => m2.default));
177289
- addDecoder(32773, () => import("./packbits-b963b38b.js").then((m2) => m2.default));
177290
- addDecoder(34887, () => import("./lerc-262d98f3.js").then((m2) => m2.default));
177291
- addDecoder(50001, () => import("./webimage-55725738.js").then((m2) => m2.default));
177357
+ addDecoder(7, () => import("./jpeg-32441425.js").then((m2) => m2.default));
177358
+ addDecoder([8, 32946], () => import("./deflate-327fa967.js").then((m2) => m2.default));
177359
+ addDecoder(32773, () => import("./packbits-b9451794.js").then((m2) => m2.default));
177360
+ addDecoder(34887, () => import("./lerc-84a2944c.js").then((m2) => m2.default));
177361
+ addDecoder(50001, () => import("./webimage-40ad658c.js").then((m2) => m2.default));
177292
177362
  function copyNewSize(array2, width2, height2, samplesPerPixel = 1) {
177293
177363
  return new (Object.getPrototypeOf(array2)).constructor(width2 * height2 * samplesPerPixel);
177294
177364
  }
@@ -191745,7 +191815,10 @@ const getPosition = (object2, { index: index2, data: data2, target: target2 }) =
191745
191815
  target2[2] = POINT_LAYER_Z_INDEX;
191746
191816
  return target2;
191747
191817
  };
191748
- const contourGetWeight = (object2, { index: index2, data: data2 }) => data2.src.featureValues[index2];
191818
+ const contourGetWeight = (object2, { index: index2, data: data2 }) => {
191819
+ var _a3;
191820
+ return (_a3 = data2.src.featureValues) == null ? void 0 : _a3[index2];
191821
+ };
191749
191822
  const contourGetPosition = (object2, { index: index2, data: data2, target: target2 }) => {
191750
191823
  target2[0] = data2.src.embeddingX[index2];
191751
191824
  target2[1] = -data2.src.embeddingY[index2];
@@ -192042,6 +192115,16 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
192042
192115
  const { obsEmbeddingIndex, obsEmbedding } = this.props;
192043
192116
  super.viewInfoDidUpdate(obsEmbeddingIndex, obsEmbedding, makeFlippedGetObsCoords);
192044
192117
  }
192118
+ componentWillUnmount() {
192119
+ delete this.cellsQuadTree;
192120
+ delete this.cellsLayer;
192121
+ delete this.cellsData;
192122
+ delete this.stratifiedData;
192123
+ delete this.cellSetsForceSimulation;
192124
+ delete this.cellSetsLabelPrevZoom;
192125
+ delete this.cellSetsLayers;
192126
+ delete this.contourLayers;
192127
+ }
192045
192128
  /**
192046
192129
  * Here, asynchronously check whether props have
192047
192130
  * updated which require re-computing memoized variables,
@@ -192248,8 +192331,9 @@ if (typeof document !== "undefined") {
192248
192331
  else
192249
192332
  document.addEventListener("DOMContentLoaded", $bbed8b41f857bcc0$var$setupGlobalEvents);
192250
192333
  }
192334
+ const FEATURE_AGGREGATION_STRATEGIES$1 = ["first", "last", "sum", "mean"];
192251
192335
  function ScatterplotOptions(props) {
192252
- const { children: children2, observationsLabel, cellRadius, setCellRadius, cellRadiusMode, setCellRadiusMode, cellOpacity, setCellOpacity, cellOpacityMode, setCellOpacityMode, cellSetLabelsVisible, setCellSetLabelsVisible, tooltipsVisible, setTooltipsVisible, cellSetLabelSize, setCellSetLabelSize, cellSetPolygonsVisible, setCellSetPolygonsVisible, cellColorEncoding, setCellColorEncoding, geneExpressionColormap, setGeneExpressionColormap, geneExpressionColormapRange, setGeneExpressionColormapRange, embeddingPointsVisible, setEmbeddingPointsVisible, embeddingContoursVisible, setEmbeddingContoursVisible, embeddingContoursFilled, setEmbeddingContoursFilled, contourPercentiles, setContourPercentiles, defaultContourPercentiles, contourColorEncoding, setContourColorEncoding } = props;
192336
+ const { children: children2, observationsLabel, cellRadius, setCellRadius, cellRadiusMode, setCellRadiusMode, cellOpacity, setCellOpacity, cellOpacityMode, setCellOpacityMode, cellSetLabelsVisible, setCellSetLabelsVisible, tooltipsVisible, setTooltipsVisible, cellSetLabelSize, setCellSetLabelSize, cellSetPolygonsVisible, setCellSetPolygonsVisible, cellColorEncoding, setCellColorEncoding, geneExpressionColormap, setGeneExpressionColormap, geneExpressionColormapRange, setGeneExpressionColormapRange, embeddingPointsVisible, setEmbeddingPointsVisible, embeddingContoursVisible, setEmbeddingContoursVisible, embeddingContoursFilled, setEmbeddingContoursFilled, contourPercentiles, setContourPercentiles, defaultContourPercentiles, contourColorEncoding, setContourColorEncoding, featureAggregationStrategy, setFeatureAggregationStrategy } = props;
192253
192337
  const scatterplotOptionsId = $bdb11010cef70236$export$f680877a34711e37();
192254
192338
  const observationsLabelNice = capitalize$2(observationsLabel);
192255
192339
  const classes = usePlotOptionsStyles();
@@ -192300,6 +192384,9 @@ function ScatterplotOptions(props) {
192300
192384
  setContourPercentiles(values3);
192301
192385
  }
192302
192386
  const handlePercentilesChangeDebounced = useCallback(debounce$5(handlePercentilesChange, 5, { trailing: true }), [handlePercentilesChange]);
192387
+ function handleFeatureAggregationStrategyChange(event2) {
192388
+ setFeatureAggregationStrategy(event2.target.value);
192389
+ }
192303
192390
  return jsxRuntimeExports.jsxs(OptionsContainer, { children: [children2, jsxRuntimeExports.jsx(CellColorEncodingOption, { observationsLabel, cellColorEncoding, setCellColorEncoding }), jsxRuntimeExports.jsxs(TableRow$1, { children: [jsxRuntimeExports.jsx(TableCell$1, { className: classes.labelCell, variant: "head", scope: "row", children: jsxRuntimeExports.jsxs("label", { htmlFor: `scatterplot-set-labels-visible-${scatterplotOptionsId}`, children: [observationsLabelNice, " Set Labels Visible"] }) }), jsxRuntimeExports.jsx(TableCell$1, { className: classes.inputCell, variant: "body", children: jsxRuntimeExports.jsx(w$3, { className: classes.checkbox, checked: cellSetLabelsVisible, onChange: handleLabelVisibilityChange, name: "scatterplot-option-cell-set-labels", color: "default", inputProps: {
192304
192391
  "aria-label": "Show or hide set labels",
192305
192392
  id: `scatterplot-set-labels-visible-${scatterplotOptionsId}`
@@ -192341,7 +192428,9 @@ function ScatterplotOptions(props) {
192341
192428
  id: `scatterplot-contours-filled-${scatterplotOptionsId}`
192342
192429
  } }) })] }), jsxRuntimeExports.jsxs(TableRow$1, { children: [jsxRuntimeExports.jsx(TableCell$1, { className: classes.labelCell, variant: "head", scope: "row", children: jsxRuntimeExports.jsx("label", { htmlFor: `scatterplot-contour-color-encoding-${scatterplotOptionsId}`, children: "Contour Color Encoding" }) }), jsxRuntimeExports.jsx(TableCell$1, { className: classes.inputCell, variant: "body", children: jsxRuntimeExports.jsxs(OptionSelect, { className: classes.select, value: contourColorEncoding, onChange: handleContourColorEncodingChange, inputProps: {
192343
192430
  id: `scatterplot-contour-color-encoding-${scatterplotOptionsId}`
192344
- }, children: [jsxRuntimeExports.jsx("option", { value: "sampleSetSelection", children: "Sample Sets" }), jsxRuntimeExports.jsxs("option", { value: "cellSetSelection", children: [observationsLabelNice, " Sets"] }), jsxRuntimeExports.jsx("option", { value: "staticColor", children: "Static Color" })] }) })] }), jsxRuntimeExports.jsxs(TableRow$1, { children: [jsxRuntimeExports.jsx(TableCell$1, { className: classes.labelCell, variant: "head", scope: "row", children: jsxRuntimeExports.jsx("label", { htmlFor: `scatterplot-contour-percentiles-${scatterplotOptionsId}`, children: "Contour Percentiles" }) }), jsxRuntimeExports.jsx(TableCell$1, { className: classes.inputCell, variant: "body", children: jsxRuntimeExports.jsx(Slider$1, { classes: { root: classes.slider, valueLabel: classes.sliderValueLabel }, value: contourPercentiles || defaultContourPercentiles, onChange: handlePercentilesChangeDebounced, "aria-label": "Scatterplot sliders for contour percentile thresholds", id: `scatterplot-contour-percentiles-${scatterplotOptionsId}`, valueLabelDisplay: "auto", step: 5e-3, min: 9e-3, max: 0.999 }) })] })] });
192431
+ }, children: [jsxRuntimeExports.jsx("option", { value: "sampleSetSelection", children: "Sample Sets" }), jsxRuntimeExports.jsxs("option", { value: "cellSetSelection", children: [observationsLabelNice, " Sets"] }), jsxRuntimeExports.jsx("option", { value: "staticColor", children: "Static Color" })] }) })] }), jsxRuntimeExports.jsxs(TableRow$1, { children: [jsxRuntimeExports.jsx(TableCell$1, { className: classes.labelCell, variant: "head", scope: "row", children: jsxRuntimeExports.jsx("label", { htmlFor: `scatterplot-contour-percentiles-${scatterplotOptionsId}`, children: "Contour Percentiles" }) }), jsxRuntimeExports.jsx(TableCell$1, { className: classes.inputCell, variant: "body", children: jsxRuntimeExports.jsx(Slider$1, { classes: { root: classes.slider, valueLabel: classes.sliderValueLabel }, value: contourPercentiles || defaultContourPercentiles, onChange: handlePercentilesChangeDebounced, "aria-label": "Scatterplot sliders for contour percentile thresholds", id: `scatterplot-contour-percentiles-${scatterplotOptionsId}`, valueLabelDisplay: "auto", step: 5e-3, min: 9e-3, max: 0.999 }) })] }), setFeatureAggregationStrategy ? jsxRuntimeExports.jsxs(TableRow$1, { children: [jsxRuntimeExports.jsx(TableCell$1, { className: classes.labelCell, variant: "head", scope: "row", children: jsxRuntimeExports.jsx("label", { htmlFor: `feature-aggregation-strategy-${scatterplotOptionsId}`, children: "Feature Aggregation Strategy" }) }), jsxRuntimeExports.jsx(TableCell$1, { className: classes.inputCell, variant: "body", children: jsxRuntimeExports.jsx(OptionSelect, { className: classes.select, value: featureAggregationStrategy ?? "first", onChange: handleFeatureAggregationStrategyChange, inputProps: {
192432
+ id: `feature-aggregation-strategy-${scatterplotOptionsId}`
192433
+ }, children: FEATURE_AGGREGATION_STRATEGIES$1.map((opt) => jsxRuntimeExports.jsx("option", { value: opt, children: capitalize$2(opt) }, opt)) }) })] }) : null] });
192345
192434
  }
192346
192435
  const styles$1 = makeStyles((theme) => ({
192347
192436
  tooltipAnchor: {
@@ -196808,8 +196897,50 @@ const titleHeight = 10;
196808
196897
  const rectHeight = 8;
196809
196898
  const rectMarginY = 2;
196810
196899
  const rectMarginX = 2;
196900
+ function combineExtents(extents, featureAggregationStrategy) {
196901
+ if (Array.isArray(extents)) {
196902
+ if (featureAggregationStrategy === "first") {
196903
+ return extents[0];
196904
+ }
196905
+ if (featureAggregationStrategy === "last") {
196906
+ return extents.at(-1);
196907
+ }
196908
+ if (typeof featureAggregationStrategy === "number") {
196909
+ const i2 = featureAggregationStrategy;
196910
+ return extents[i2];
196911
+ }
196912
+ if (featureAggregationStrategy === "sum") {
196913
+ return extents.reduce((a2, h2) => [a2[0] + h2[0], a2[1] + h2[1]]);
196914
+ }
196915
+ if (featureAggregationStrategy === "mean") {
196916
+ return extents.reduce((a2, h2) => [a2[0] + h2[0], a2[1] + h2[1]]).map((v2) => v2 / extents.length);
196917
+ }
196918
+ }
196919
+ return null;
196920
+ }
196921
+ function combineMissings(missings, featureAggregationStrategy) {
196922
+ if (Array.isArray(missings)) {
196923
+ if (featureAggregationStrategy === "first") {
196924
+ return missings[0];
196925
+ }
196926
+ if (featureAggregationStrategy === "last") {
196927
+ return missings.at(-1);
196928
+ }
196929
+ if (typeof featureAggregationStrategy === "number") {
196930
+ const i2 = featureAggregationStrategy;
196931
+ return missings[i2];
196932
+ }
196933
+ if (featureAggregationStrategy === "sum") {
196934
+ return missings.reduce((a2, h2) => a2 + h2, 0);
196935
+ }
196936
+ if (featureAggregationStrategy === "mean") {
196937
+ return missings.reduce((a2, h2) => a2 + h2 / missings.length, 0);
196938
+ }
196939
+ }
196940
+ return null;
196941
+ }
196811
196942
  function Legend(props) {
196812
- const { visible: visibleProp, positionRelative = false, highContrast = false, obsType, featureValueType, considerSelections = true, obsColorEncoding, featureSelection, featureLabelsMap, featureValueColormap, featureValueColormapRange, spatialChannelColor, spatialLayerColor, obsSetSelection, obsSetColor, extent: extent2, missing, width: width2 = 100, height: height2 = 36, theme, showObsLabel = false, pointsVisible = true, contoursVisible = false, contoursFilled, contourPercentiles, contourThresholds } = props;
196943
+ const { visible: visibleProp, positionRelative = false, highContrast = false, obsType, featureValueType, considerSelections = true, obsColorEncoding, featureSelection, featureLabelsMap, featureValueColormap, featureValueColormapRange, spatialChannelColor, spatialLayerColor, obsSetSelection, obsSetColor, featureAggregationStrategy, extent: extent2, missing, width: width2 = 100, height: height2 = 36, theme, showObsLabel = false, pointsVisible = true, contoursVisible = false, contoursFilled, contourPercentiles, contourThresholds } = props;
196813
196944
  const svgRef = useRef();
196814
196945
  const classes = useStyles$p();
196815
196946
  const isDarkTheme = theme === "dark";
@@ -196818,9 +196949,9 @@ function Legend(props) {
196818
196949
  const layerColor = Array.isArray(spatialLayerColor) && spatialLayerColor.length === 3 ? spatialLayerColor : getDefaultColor(theme);
196819
196950
  const channelColor = Array.isArray(spatialChannelColor) && spatialChannelColor.length === 3 ? spatialChannelColor : getDefaultColor(theme);
196820
196951
  const staticColor = obsColorEncoding === "spatialChannelColor" ? channelColor : layerColor;
196821
- const visible = visibleProp && (!considerSelections || obsColorEncoding === "geneSelection" && featureSelection && Array.isArray(featureSelection) && featureSelection.length === 1 || isSetColor && (obsSetSelection == null ? void 0 : obsSetSelection.length) > 0 && (obsSetColor == null ? void 0 : obsSetColor.length) > 0 || isStaticColor);
196952
+ const visible = visibleProp && (!considerSelections || obsColorEncoding === "geneSelection" && featureSelection && Array.isArray(featureSelection) && featureSelection.length >= 1 || isSetColor && (obsSetSelection == null ? void 0 : obsSetSelection.length) > 0 && (obsSetColor == null ? void 0 : obsSetColor.length) > 0 || isStaticColor);
196822
196953
  const levelZeroNames = useMemo(() => Array.from(new Set((obsSetSelection == null ? void 0 : obsSetSelection.map((setPath) => setPath[0])) || [])), [obsSetSelection]);
196823
- const dynamicHeight = isSetColor ? levelZeroNames.length * titleHeight + (obsSetSelection == null ? void 0 : obsSetSelection.length) * (rectHeight + rectMarginY) : height2 + (!pointsVisible && contoursVisible ? 25 : 0);
196954
+ const dynamicHeight = isSetColor && obsSetSelection ? levelZeroNames.length * titleHeight + (obsSetSelection == null ? void 0 : obsSetSelection.length) * (rectHeight + rectMarginY) : height2 + (!pointsVisible && contoursVisible ? 25 : 0);
196824
196955
  useEffect(() => {
196825
196956
  const domElement = svgRef.current;
196826
196957
  const foregroundColor = highContrast ? "black" : isDarkTheme ? "white" : "black";
@@ -196829,7 +196960,7 @@ function Legend(props) {
196829
196960
  svg2.attr("width", width2).attr("height", dynamicHeight);
196830
196961
  const g2 = svg2.append("g").attr("width", width2).attr("height", dynamicHeight);
196831
196962
  if (!considerSelections || obsColorEncoding === "geneSelection") {
196832
- const [xMin, xMax] = extent2 || [0, 1];
196963
+ const [xMin, xMax] = combineExtents(extent2, featureAggregationStrategy) || [0, 1];
196833
196964
  if (featureValueColormap && pointsVisible) {
196834
196965
  const xlinkHref = getXlinkHref(featureValueColormap);
196835
196966
  g2.append("image").attr("x", 0).attr("y", titleHeight).attr("width", width2).attr("height", rectHeight).attr("preserveAspectRatio", "none").attr("href", xlinkHref);
@@ -196893,8 +197024,19 @@ function Legend(props) {
196893
197024
  });
196894
197025
  });
196895
197026
  }
196896
- const featureSelectionLabelRaw = featureSelection && featureSelection.length >= 1 && !isStaticColor ? (featureLabelsMap == null ? void 0 : featureLabelsMap.get(featureSelection[0])) || (featureLabelsMap == null ? void 0 : featureLabelsMap.get(cleanFeatureId(featureSelection[0]))) || featureSelection[0] : null;
196897
- const featureSelectionLabel = missing ? `${featureSelectionLabelRaw} (${Math.round(missing * 100)}% NaN)` : featureSelectionLabelRaw;
197027
+ const featureSelectionLabelRaw = featureSelection && featureSelection.length >= 1 && !isStaticColor ? featureSelection.map((geneName) => (featureLabelsMap == null ? void 0 : featureLabelsMap.get(geneName)) || (featureLabelsMap == null ? void 0 : featureLabelsMap.get(cleanFeatureId(geneName))) || geneName) : null;
197028
+ let featureSelectionLabelRawStr = "";
197029
+ if (featureAggregationStrategy === "first") {
197030
+ featureSelectionLabelRawStr = featureSelectionLabelRaw == null ? void 0 : featureSelectionLabelRaw[0];
197031
+ } else if (featureAggregationStrategy === "last") {
197032
+ featureSelectionLabelRawStr = featureSelectionLabelRaw == null ? void 0 : featureSelectionLabelRaw.at(-1);
197033
+ } else if (featureAggregationStrategy === "sum") {
197034
+ featureSelectionLabelRawStr = "Sum of features";
197035
+ } else if (featureAggregationStrategy === "mean") {
197036
+ featureSelectionLabelRawStr = "Mean of features";
197037
+ }
197038
+ const combinedMissing = combineMissings(missing, featureAggregationStrategy);
197039
+ const featureSelectionLabel = combinedMissing ? `${featureSelectionLabelRawStr} (${Math.round(combinedMissing * 100)}% NaN)` : featureSelectionLabelRawStr;
196898
197040
  const obsLabel = capitalize$2(obsType);
196899
197041
  const featureLabel = considerSelections ? featureSelectionLabel || capitalize$2(featureValueType) : capitalize$2(featureValueType);
196900
197042
  const mainLabel = showObsLabel ? obsLabel : featureLabel;
@@ -196928,7 +197070,8 @@ function Legend(props) {
196928
197070
  contourThresholds,
196929
197071
  contoursFilled,
196930
197072
  contoursVisible,
196931
- pointsVisible
197073
+ pointsVisible,
197074
+ featureAggregationStrategy
196932
197075
  ]);
196933
197076
  return jsxRuntimeExports.jsx("div", { className: clsx(classes.legend, {
196934
197077
  [classes.legendRelative]: positionRelative,
@@ -197089,6 +197232,7 @@ function ChannelNamesLegend(props) {
197089
197232
  }) : null });
197090
197233
  }
197091
197234
  const DEFAULT_CONTOUR_PERCENTILES = [0.09, 0.9, 0.99];
197235
+ const DEFAULT_FEATURE_AGGREGATION_STRATEGY$1 = "first";
197092
197236
  function EmbeddingScatterplotSubscriber(props) {
197093
197237
  const {
197094
197238
  uuid,
@@ -197108,10 +197252,11 @@ function EmbeddingScatterplotSubscriber(props) {
197108
197252
  const loaders = useLoaders();
197109
197253
  const setComponentHover = useSetComponentHover();
197110
197254
  const setComponentViewInfo = useSetComponentViewInfo(uuid);
197111
- const [{ dataset, obsType, featureType, featureValueType, sampleType, embeddingZoom: zoom2, embeddingTargetX: targetX2, embeddingTargetY: targetY2, embeddingTargetZ: targetZ, embeddingType: mapping, obsFilter: cellFilter, obsHighlight: cellHighlight, featureSelection: geneSelection, obsSetSelection: cellSetSelection, obsSetColor: cellSetColor, obsColorEncoding: cellColorEncoding, additionalObsSets: additionalCellSets, embeddingObsSetPolygonsVisible: cellSetPolygonsVisible, embeddingObsSetLabelsVisible: cellSetLabelsVisible, embeddingObsSetLabelSize: cellSetLabelSize, embeddingObsRadius: cellRadiusFixed, embeddingObsRadiusMode: cellRadiusMode, embeddingObsOpacity: cellOpacityFixed, embeddingObsOpacityMode: cellOpacityMode, featureValueColormap: geneExpressionColormap, featureValueColormapRange: geneExpressionColormapRange, tooltipsVisible, sampleSetSelection: sampleSetSelectionFromCoordination, sampleSetColor, embeddingPointsVisible, embeddingContoursVisible, embeddingContoursFilled, embeddingContourPercentiles: contourPercentiles, contourColorEncoding, contourColor }, { setEmbeddingZoom: setZoom, setEmbeddingTargetX: setTargetX, setEmbeddingTargetY: setTargetY, setEmbeddingTargetZ: setTargetZ, setObsFilter: setCellFilter, setObsSetSelection: setCellSetSelection, setObsHighlight: setCellHighlight, setObsSetColor: setCellSetColor, setObsColorEncoding: setCellColorEncoding, setAdditionalObsSets: setAdditionalCellSets, setEmbeddingObsSetPolygonsVisible: setCellSetPolygonsVisible, setEmbeddingObsSetLabelsVisible: setCellSetLabelsVisible, setEmbeddingObsSetLabelSize: setCellSetLabelSize, setEmbeddingObsRadius: setCellRadiusFixed, setEmbeddingObsRadiusMode: setCellRadiusMode, setEmbeddingObsOpacity: setCellOpacityFixed, setEmbeddingObsOpacityMode: setCellOpacityMode, setFeatureValueColormap: setGeneExpressionColormap, setFeatureValueColormapRange: setGeneExpressionColormapRange, setTooltipsVisible, setEmbeddingPointsVisible, setEmbeddingContoursVisible, setEmbeddingContoursFilled, setEmbeddingContourPercentiles: setContourPercentiles, setContourColorEncoding }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType$1.SCATTERPLOT], coordinationScopes);
197255
+ const [{ dataset, obsType, featureType, featureValueType, sampleType, embeddingZoom: zoom2, embeddingTargetX: targetX2, embeddingTargetY: targetY2, embeddingTargetZ: targetZ, embeddingType: mapping, obsFilter: cellFilter, obsHighlight: cellHighlight, featureSelection: geneSelection, obsSetSelection: cellSetSelection, obsSetColor: cellSetColor, obsColorEncoding: cellColorEncoding, additionalObsSets: additionalCellSets, embeddingObsSetPolygonsVisible: cellSetPolygonsVisible, embeddingObsSetLabelsVisible: cellSetLabelsVisible, embeddingObsSetLabelSize: cellSetLabelSize, embeddingObsRadius: cellRadiusFixed, embeddingObsRadiusMode: cellRadiusMode, embeddingObsOpacity: cellOpacityFixed, embeddingObsOpacityMode: cellOpacityMode, featureValueColormap: geneExpressionColormap, featureValueColormapRange: geneExpressionColormapRange, tooltipsVisible, sampleSetSelection: sampleSetSelectionFromCoordination, sampleSetColor, embeddingPointsVisible, embeddingContoursVisible, embeddingContoursFilled, embeddingContourPercentiles: contourPercentiles, contourColorEncoding, contourColor, featureAggregationStrategy }, { setEmbeddingZoom: setZoom, setEmbeddingTargetX: setTargetX, setEmbeddingTargetY: setTargetY, setEmbeddingTargetZ: setTargetZ, setObsFilter: setCellFilter, setObsSetSelection: setCellSetSelection, setObsHighlight: setCellHighlight, setObsSetColor: setCellSetColor, setObsColorEncoding: setCellColorEncoding, setAdditionalObsSets: setAdditionalCellSets, setEmbeddingObsSetPolygonsVisible: setCellSetPolygonsVisible, setEmbeddingObsSetLabelsVisible: setCellSetLabelsVisible, setEmbeddingObsSetLabelSize: setCellSetLabelSize, setEmbeddingObsRadius: setCellRadiusFixed, setEmbeddingObsRadiusMode: setCellRadiusMode, setEmbeddingObsOpacity: setCellOpacityFixed, setEmbeddingObsOpacityMode: setCellOpacityMode, setFeatureValueColormap: setGeneExpressionColormap, setFeatureValueColormapRange: setGeneExpressionColormapRange, setTooltipsVisible, setEmbeddingPointsVisible, setEmbeddingContoursVisible, setEmbeddingContoursFilled, setEmbeddingContourPercentiles: setContourPercentiles, setContourColorEncoding, setFeatureAggregationStrategy }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType$1.SCATTERPLOT], coordinationScopes);
197112
197256
  const { embeddingZoom: initialZoom, embeddingTargetX: initialTargetX, embeddingTargetY: initialTargetY } = useInitialCoordination(COMPONENT_COORDINATION_TYPES[ViewType$1.SCATTERPLOT], coordinationScopes);
197113
197257
  const observationsLabel = observationsLabelOverride || obsType;
197114
197258
  const sampleSetSelection = sampleSetSelectionFromProps || sampleSetSelectionFromCoordination;
197259
+ const featureAggregationStrategyToUse = featureAggregationStrategy ?? DEFAULT_FEATURE_AGGREGATION_STRATEGY$1;
197115
197260
  const [width2, height2, deckRef] = useDeckCanvasSize();
197116
197261
  const title2 = titleOverride || `Scatterplot (${mapping})`;
197117
197262
  const [obsLabelsTypes, obsLabelsData] = useMultiObsLabels(coordinationScopes, obsType, loaders, dataset);
@@ -197214,7 +197359,7 @@ function EmbeddingScatterplotSubscriber(props) {
197214
197359
  return [null, null, null, null, null];
197215
197360
  }, [obsEmbedding]);
197216
197361
  useEffect(() => {
197217
- if (xRange && yRange) {
197362
+ if (xRange && yRange && width2 && height2) {
197218
197363
  const pointSizeDevicePixels = getPointSizeDevicePixels(window.devicePixelRatio, zoom2, xRange, yRange, width2, height2);
197219
197364
  setDynamicCellRadius(pointSizeDevicePixels);
197220
197365
  const nextCellOpacityScale = getPointOpacity(zoom2, xRange, yRange, width2, height2, numCells, averageFillDensity);
@@ -197283,6 +197428,9 @@ function EmbeddingScatterplotSubscriber(props) {
197283
197428
  originalViewState.target[1]
197284
197429
  ];
197285
197430
  const scaleFactor = 2 ** originalViewState.zoom;
197431
+ if (!(typeof scaleFactor === "number" && typeof center2[0] === "number" && typeof center2[1] === "number") || Number.isNaN(scaleFactor)) {
197432
+ return null;
197433
+ }
197286
197434
  const radius2 = Math.min(width2, height2) / 2 / scaleFactor;
197287
197435
  const numPoints = 96;
197288
197436
  const options = { steps: numPoints, units: "degrees" };
@@ -197327,17 +197475,16 @@ function EmbeddingScatterplotSubscriber(props) {
197327
197475
  }
197328
197476
  return null;
197329
197477
  }, [sampleEdges]);
197330
- const stratifiedData = useMemo(() => {
197478
+ const [stratifiedData, stratifiedDataCount] = useMemo(() => {
197331
197479
  if (alignedEmbeddingData == null ? void 0 : alignedEmbeddingData.data) {
197332
- const result = stratifyArrays(sampleEdges, sampleIdToObsIdsMap, sampleSets, sampleSetSelection, alignedEmbeddingIndex, mergedCellSets, cellSetSelection, {
197480
+ const [result, cellCountResult] = stratifyArrays(sampleEdges, sampleIdToObsIdsMap, sampleSets, sampleSetSelection, alignedEmbeddingIndex, mergedCellSets, cellSetSelection, {
197333
197481
  obsEmbeddingX: alignedEmbeddingData.data[0],
197334
197482
  obsEmbeddingY: alignedEmbeddingData.data[1],
197335
- // TODO: aggregate and transform expression data if needed prior to passing here
197336
- ...(uint8ExpressionData == null ? void 0 : uint8ExpressionData[0]) ? { featureValue: uint8ExpressionData == null ? void 0 : uint8ExpressionData[0] } : {}
197337
- });
197338
- return result;
197483
+ ...(uint8ExpressionData == null ? void 0 : uint8ExpressionData[0]) ? { featureValue: uint8ExpressionData } : {}
197484
+ }, featureAggregationStrategyToUse);
197485
+ return [result, cellCountResult];
197339
197486
  }
197340
- return null;
197487
+ return [null, null];
197341
197488
  }, [
197342
197489
  alignedEmbeddingIndex,
197343
197490
  alignedEmbeddingData,
@@ -197347,7 +197494,8 @@ function EmbeddingScatterplotSubscriber(props) {
197347
197494
  sampleSets,
197348
197495
  sampleSetSelection,
197349
197496
  cellSetSelection,
197350
- mergedCellSets
197497
+ mergedCellSets,
197498
+ featureAggregationStrategyToUse
197351
197499
  ]);
197352
197500
  const setViewState = ({ zoom: newZoom, target: target2 }) => {
197353
197501
  setZoom(newZoom);
@@ -197355,7 +197503,8 @@ function EmbeddingScatterplotSubscriber(props) {
197355
197503
  setTargetY(target2[1]);
197356
197504
  setTargetZ(target2[2] || 0);
197357
197505
  };
197358
- return jsxRuntimeExports.jsxs(TitleInfo, { title: title2, info: `${commaNumber(cellsCount)} ${pluralize(observationsLabel, cellsCount)}`, closeButtonVisible, downloadButtonVisible, removeGridComponent, urls: urls2, theme, isReady, helpText, options: jsxRuntimeExports.jsx(ScatterplotOptions, { observationsLabel, cellRadius: cellRadiusFixed, setCellRadius: setCellRadiusFixed, cellRadiusMode, setCellRadiusMode, cellOpacity: cellOpacityFixed, setCellOpacity: setCellOpacityFixed, cellOpacityMode, setCellOpacityMode, cellSetLabelsVisible, setCellSetLabelsVisible, tooltipsVisible, setTooltipsVisible, cellSetLabelSize, setCellSetLabelSize, cellSetPolygonsVisible, setCellSetPolygonsVisible, cellColorEncoding, setCellColorEncoding, geneExpressionColormap, setGeneExpressionColormap, geneExpressionColormapRange, setGeneExpressionColormapRange, embeddingPointsVisible, setEmbeddingPointsVisible, embeddingContoursVisible, setEmbeddingContoursVisible, embeddingContoursFilled, setEmbeddingContoursFilled, contourPercentiles, setContourPercentiles, defaultContourPercentiles: DEFAULT_CONTOUR_PERCENTILES, contourColorEncoding, setContourColorEncoding }), children: [jsxRuntimeExports.jsx(ScatterplotWrapper, {
197506
+ const cellCountToUse = embeddingPointsVisible ? cellsCount : stratifiedDataCount ?? cellsCount;
197507
+ return jsxRuntimeExports.jsxs(TitleInfo, { title: title2, info: `${commaNumber(cellCountToUse)} ${pluralize(observationsLabel, cellCountToUse)}`, closeButtonVisible, downloadButtonVisible, removeGridComponent, urls: urls2, theme, isReady, helpText, options: jsxRuntimeExports.jsx(ScatterplotOptions, { observationsLabel, cellRadius: cellRadiusFixed, setCellRadius: setCellRadiusFixed, cellRadiusMode, setCellRadiusMode, cellOpacity: cellOpacityFixed, setCellOpacity: setCellOpacityFixed, cellOpacityMode, setCellOpacityMode, cellSetLabelsVisible, setCellSetLabelsVisible, tooltipsVisible, setTooltipsVisible, cellSetLabelSize, setCellSetLabelSize, cellSetPolygonsVisible, setCellSetPolygonsVisible, cellColorEncoding, setCellColorEncoding, geneExpressionColormap, setGeneExpressionColormap, geneExpressionColormapRange, setGeneExpressionColormapRange, embeddingPointsVisible, setEmbeddingPointsVisible, embeddingContoursVisible, setEmbeddingContoursVisible, embeddingContoursFilled, setEmbeddingContoursFilled, contourPercentiles, setContourPercentiles, defaultContourPercentiles: DEFAULT_CONTOUR_PERCENTILES, contourColorEncoding, setContourColorEncoding, featureAggregationStrategy, setFeatureAggregationStrategy }), children: [jsxRuntimeExports.jsx(ScatterplotWrapper, {
197359
197508
  ref: deckRef,
197360
197509
  uuid,
197361
197510
  theme,
@@ -197401,7 +197550,7 @@ function EmbeddingScatterplotSubscriber(props) {
197401
197550
  embeddingContoursVisible,
197402
197551
  circleInfo,
197403
197552
  featureSelection: geneSelection
197404
- }), tooltipsVisible && jsxRuntimeExports.jsx(ScatterplotTooltipSubscriber, { parentUuid: uuid, obsHighlight: cellHighlight, width: width2, height: height2, getObsInfo: getObsInfo2, featureType, featureLabelsMap }), jsxRuntimeExports.jsx(Legend, {
197553
+ }), tooltipsVisible && width2 && height2 ? jsxRuntimeExports.jsx(ScatterplotTooltipSubscriber, { parentUuid: uuid, obsHighlight: cellHighlight, width: width2, height: height2, getObsInfo: getObsInfo2, featureType, featureLabelsMap }) : null, jsxRuntimeExports.jsx(Legend, {
197405
197554
  visible: true,
197406
197555
  theme,
197407
197556
  featureType,
@@ -197412,14 +197561,15 @@ function EmbeddingScatterplotSubscriber(props) {
197412
197561
  featureValueColormap: geneExpressionColormap,
197413
197562
  featureValueColormapRange: geneExpressionColormapRange,
197414
197563
  obsSetSelection: cellSetSelection,
197415
- extent: expressionExtents == null ? void 0 : expressionExtents[0],
197416
- missing: expressionMissing == null ? void 0 : expressionMissing[0],
197564
+ extent: expressionExtents,
197565
+ missing: expressionMissing,
197417
197566
  // Contour percentile legend
197418
197567
  pointsVisible: embeddingPointsVisible,
197419
197568
  contoursVisible: embeddingContoursVisible,
197420
197569
  contoursFilled: embeddingContoursFilled,
197421
197570
  contourPercentiles: contourPercentiles || DEFAULT_CONTOUR_PERCENTILES,
197422
- contourThresholds
197571
+ contourThresholds,
197572
+ featureAggregationStrategy: featureAggregationStrategyToUse
197423
197573
  })] });
197424
197574
  }
197425
197575
  function DualEmbeddingScatterplotSubscriber(props) {
@@ -212858,9 +213008,6 @@ function physicalSizeToMatrix(xSize, ySize, zSize, xUnit, yUnit, zUnit) {
212858
213008
  sizes.push(unit$1(`${zSize} ${zUnit}`.replace("µ", "u")));
212859
213009
  }
212860
213010
  const scale2 = sizes.map((i2) => divide(i2, unit$1("1 um")));
212861
- if (!sizes[0].equals(sizes[1])) {
212862
- scale2[1] = divide(sizes[1], sizes[0]);
212863
- }
212864
213011
  if (!scale2[2]) {
212865
213012
  scale2[2] = 1;
212866
213013
  }
@@ -216364,6 +216511,7 @@ let Spatial$1 = class Spatial extends AbstractSpatialOrScatterplot {
216364
216511
  return null;
216365
216512
  }
216366
216513
  createRasterLayer(rawLayerDef, loader2, i2) {
216514
+ const { photometricInterpretation } = this.props;
216367
216515
  const layerDef = {
216368
216516
  ...rawLayerDef,
216369
216517
  channels: rawLayerDef.channels.filter((channel) => channel.selection && channel.color && channel.slider)
@@ -216442,6 +216590,23 @@ let Spatial$1 = class Spatial extends AbstractSpatialOrScatterplot {
216442
216590
  if (isInterleaved$1((Array.isArray(data2) ? data2[0] : data2).shape)) {
216443
216591
  rgbInterleavedProps.visible = layerDef.visible;
216444
216592
  }
216593
+ const rgbProps = photometricInterpretation === "RGB" ? {
216594
+ colors: [
216595
+ [255, 0, 0],
216596
+ [0, 255, 0],
216597
+ [0, 0, 255]
216598
+ ],
216599
+ contrastLimits: [
216600
+ [0, 255],
216601
+ [0, 255],
216602
+ [0, 255]
216603
+ ],
216604
+ channelsVisible: [
216605
+ true,
216606
+ true,
216607
+ true
216608
+ ]
216609
+ } : {};
216445
216610
  return new Layer2({
216446
216611
  loader: layerLoader,
216447
216612
  id: `${layerDef.use3d ? "volume" : "image"}-layer-${layerDef.index}-${i2}`,
@@ -216463,7 +216628,8 @@ let Spatial$1 = class Spatial extends AbstractSpatialOrScatterplot {
216463
216628
  onViewportLoad: layerProps.callback,
216464
216629
  excludeBackground: layerProps.excludeBackground,
216465
216630
  extensions,
216466
- ...rgbInterleavedProps
216631
+ ...rgbInterleavedProps,
216632
+ ...rgbProps
216467
216633
  });
216468
216634
  }
216469
216635
  use3d() {
@@ -216682,7 +216848,8 @@ let Spatial$1 = class Spatial extends AbstractSpatialOrScatterplot {
216682
216848
  "geneExpressionColormapRange",
216683
216849
  "expressionData",
216684
216850
  "imageLayerCallbacks",
216685
- "geneExpressionColormap"
216851
+ "geneExpressionColormap",
216852
+ "photometricInterpretation"
216686
216853
  ].some(shallowDiff)) {
216687
216854
  this.onUpdateImages();
216688
216855
  forceUpdate = true;
@@ -216781,7 +216948,7 @@ function SpatialSubscriber$1(props) {
216781
216948
  const loaders = useLoaders();
216782
216949
  const setComponentHover = useSetComponentHover();
216783
216950
  const setComponentViewInfo = useSetComponentViewInfo(uuid);
216784
- const [{ dataset, obsType, featureType, featureValueType, spatialZoom: zoom2, spatialTargetX: targetX2, spatialTargetY: targetY2, spatialTargetZ: targetZ, spatialRotationX: rotationX, spatialRotationY: rotationY, spatialRotationZ: rotationZ, spatialRotationOrbit: rotationOrbit, spatialOrbitAxis: orbitAxis, spatialImageLayer: imageLayers, spatialSegmentationLayer: cellsLayer, spatialPointLayer: moleculesLayer, spatialNeighborhoodLayer: neighborhoodsLayer, obsFilter: cellFilter, obsHighlight: cellHighlight, moleculeHighlight, featureSelection: geneSelection, obsSetSelection: cellSetSelection, obsSetColor: cellSetColor, obsColorEncoding: cellColorEncoding, additionalObsSets: additionalCellSets, spatialAxisFixed, featureValueColormap: geneExpressionColormap, featureValueColormapRange: geneExpressionColormapRange, tooltipsVisible }, { setSpatialZoom: setZoom, setSpatialTargetX: setTargetX, setSpatialTargetY: setTargetY, setSpatialTargetZ: setTargetZ, setSpatialRotationX: setRotationX, setSpatialRotationOrbit: setRotationOrbit, setSpatialOrbitAxis: setOrbitAxis, setSpatialImageLayer: setRasterLayers, setSpatialSegmentationLayer: setCellsLayer, setSpatialPointLayer: setMoleculesLayer, setSpatialNeighborhoodLayer: setNeighborhoodsLayer, setObsFilter: setCellFilter, setObsSetSelection: setCellSetSelection, setObsHighlight: setCellHighlight, setObsSetColor: setCellSetColor, setObsColorEncoding: setCellColorEncoding, setAdditionalObsSets: setAdditionalCellSets, setMoleculeHighlight, setSpatialAxisFixed, setFeatureValueColormap: setGeneExpressionColormap, setFeatureValueColormapRange: setGeneExpressionColormapRange, setTooltipsVisible }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType$1.SPATIAL], coordinationScopes);
216951
+ const [{ dataset, obsType, featureType, featureValueType, spatialZoom: zoom2, spatialTargetX: targetX2, spatialTargetY: targetY2, spatialTargetZ: targetZ, spatialRotationX: rotationX, spatialRotationY: rotationY, spatialRotationZ: rotationZ, spatialRotationOrbit: rotationOrbit, spatialOrbitAxis: orbitAxis, spatialImageLayer: imageLayers, spatialSegmentationLayer: cellsLayer, spatialPointLayer: moleculesLayer, spatialNeighborhoodLayer: neighborhoodsLayer, obsFilter: cellFilter, obsHighlight: cellHighlight, moleculeHighlight, featureSelection: geneSelection, obsSetSelection: cellSetSelection, obsSetColor: cellSetColor, obsColorEncoding: cellColorEncoding, additionalObsSets: additionalCellSets, spatialAxisFixed, featureValueColormap: geneExpressionColormap, featureValueColormapRange: geneExpressionColormapRange, tooltipsVisible, photometricInterpretation: photometricInterpretationFromCoordination }, { setSpatialZoom: setZoom, setSpatialTargetX: setTargetX, setSpatialTargetY: setTargetY, setSpatialTargetZ: setTargetZ, setSpatialRotationX: setRotationX, setSpatialRotationOrbit: setRotationOrbit, setSpatialOrbitAxis: setOrbitAxis, setSpatialImageLayer: setRasterLayers, setSpatialSegmentationLayer: setCellsLayer, setSpatialPointLayer: setMoleculesLayer, setSpatialNeighborhoodLayer: setNeighborhoodsLayer, setObsFilter: setCellFilter, setObsSetSelection: setCellSetSelection, setObsHighlight: setCellHighlight, setObsSetColor: setCellSetColor, setObsColorEncoding: setCellColorEncoding, setAdditionalObsSets: setAdditionalCellSets, setMoleculeHighlight, setSpatialAxisFixed, setFeatureValueColormap: setGeneExpressionColormap, setFeatureValueColormapRange: setGeneExpressionColormapRange, setTooltipsVisible }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType$1.SPATIAL], coordinationScopes);
216785
216952
  const { spatialZoom: initialZoom, spatialTargetX: initialTargetX, spatialTargetY: initialTargetY, spatialTargetZ: initialTargetZ } = useInitialCoordination(COMPONENT_COORDINATION_TYPES[ViewType$1.SPATIAL], coordinationScopes);
216786
216953
  const observationsLabel = observationsLabelOverride || obsType;
216787
216954
  const [{ imageLayerCallbacks, segmentationLayerCallbacks }] = useAuxiliaryCoordination(COMPONENT_COORDINATION_TYPES.layerController, coordinationScopes);
@@ -216801,10 +216968,11 @@ function SpatialSubscriber$1(props) {
216801
216968
  const [expressionData, loadedFeatureSelection, featureSelectionStatus] = useFeatureSelection(loaders, dataset, false, geneSelection, { obsType, featureType, featureValueType });
216802
216969
  const [{ obsIndex: matrixObsIndex }, matrixIndicesStatus, matrixIndicesUrls] = useObsFeatureMatrixIndices(loaders, dataset, false, { obsType, featureType, featureValueType });
216803
216970
  const [{ image: image2 }, imageStatus, imageUrls] = useImageData(loaders, dataset, false, { setSpatialImageLayer: setRasterLayers }, { spatialImageLayer: imageLayers }, {});
216804
- const { loaders: imageLayerLoaders = [], meta: meta2 = [] } = image2 || {};
216971
+ const { loaders: imageLayerLoaders = [], meta: meta2 = [], instance: instance2 } = image2 || {};
216805
216972
  const [neighborhoods, neighborhoodsStatus, neighborhoodsUrls] = useNeighborhoodsData(loaders, dataset, false, { setSpatialNeighborhoodLayer: setNeighborhoodsLayer }, { spatialNeighborhoodLayer: neighborhoodsLayer });
216806
216973
  const [{ featureLabelsMap: featureLabelsMapOrig }, featureLabelsStatus, featureLabelsUrls] = useFeatureLabelsData(loaders, dataset, false, {}, {}, { featureType });
216807
216974
  const [featureLabelsMap, expandedFeatureLabelsStatus] = useExpandedFeatureLabelsMap(featureType, featureLabelsMapOrig, { stripCuriePrefixes: true });
216975
+ const photometricInterpretation = photometricInterpretationFromCoordination ?? (instance2 == null ? void 0 : instance2.getPhotometricInterpretation());
216808
216976
  const isReady = useReady([
216809
216977
  obsLocationsStatus,
216810
216978
  obsLabelsStatus,
@@ -217057,7 +217225,7 @@ function SpatialSubscriber$1(props) {
217057
217225
  orbitAxis
217058
217226
  }, setViewState, originalViewState, imageLayerDefs: imageLayers, obsSegmentationsLayerDefs: cellsLayer, obsLocationsLayerDefs: moleculesLayer, neighborhoodLayerDefs: neighborhoodsLayer, obsLocationsIndex, obsSegmentationsIndex, obsLocations, obsLocationsLabels, obsLocationsFeatureIndex, hasSegmentations: hasSegmentationsData, obsSegmentations, obsSegmentationsType, obsCentroids, obsCentroidsIndex, cellFilter, cellSelection, cellHighlight, cellColors, neighborhoods, imageLayerLoaders: resolutionFilteredImageLayerLoaders, setCellFilter, setCellSelection: setCellSelectionProp, setCellHighlight, setHoverInfo, setMoleculeHighlight, setComponentHover: () => {
217059
217227
  setComponentHover(uuid);
217060
- }, updateViewInfo: setComponentViewInfo, imageLayerCallbacks, segmentationLayerCallbacks, spatialAxisFixed, geneExpressionColormap, geneExpressionColormapRange, expressionData: shiftedExpressionDataForBitmask, cellColorEncoding, getExpressionValue, theme, useFullResolutionImage }), tooltipsVisible && jsxRuntimeExports.jsx(SpatialTooltipSubscriber$1, { parentUuid: uuid, obsHighlight: cellHighlight || moleculeHighlight, width: width2, height: height2, getObsInfo: getTooltipObsInfo, useHoverInfoForTooltip, hoverData, hoverCoord, hoverMode, getObsIdFromHoverData, featureType, featureLabelsMap }), jsxRuntimeExports.jsx(Legend, {
217228
+ }, updateViewInfo: setComponentViewInfo, imageLayerCallbacks, segmentationLayerCallbacks, spatialAxisFixed, geneExpressionColormap, geneExpressionColormapRange, expressionData: shiftedExpressionDataForBitmask, cellColorEncoding, getExpressionValue, theme, useFullResolutionImage, photometricInterpretation }), tooltipsVisible && jsxRuntimeExports.jsx(SpatialTooltipSubscriber$1, { parentUuid: uuid, obsHighlight: cellHighlight || moleculeHighlight, width: width2, height: height2, getObsInfo: getTooltipObsInfo, useHoverInfoForTooltip, hoverData, hoverCoord, hoverMode, getObsIdFromHoverData, featureType, featureLabelsMap }), jsxRuntimeExports.jsx(Legend, {
217061
217229
  visible: true,
217062
217230
  // Fix to dark theme due to black background of spatial plot.
217063
217231
  theme: "dark",
@@ -218490,7 +218658,7 @@ class ErrorBoundary extends React__default.Component {
218490
218658
  }
218491
218659
  }
218492
218660
  const LazySpatialThree = React__default.lazy(async () => {
218493
- const { SpatialWrapper: SpatialWrapper2 } = await import("./index-7b4cc1b8.js");
218661
+ const { SpatialWrapper: SpatialWrapper2 } = await import("./index-fd7c132d.js");
218494
218662
  return { default: SpatialWrapper2 };
218495
218663
  });
218496
218664
  const SpatialThreeAdapter = React__default.forwardRef((props, ref2) => jsxRuntimeExports.jsx("div", { ref: ref2, style: { width: "100%", height: "100%" }, children: jsxRuntimeExports.jsx(ErrorBoundary, { children: jsxRuntimeExports.jsx(Suspense, { fallback: jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: jsxRuntimeExports.jsx(LazySpatialThree, { ...props }) }) }) }));
@@ -225003,7 +225171,7 @@ const buttonStyles = {
225003
225171
  };
225004
225172
  function LayerController$1(props) {
225005
225173
  var _a3;
225006
- const { layer, name: name2, loader: loader2, theme, handleLayerRemove, handleLayerChange, shouldShowTransparentColor, shouldShowDomain, shouldShowColormap, ChannelController, setViewState, disable3d, setImageLayerCallback, setAreLayerChannelsLoading, areLayerChannelsLoading, disabled, spatialHeight, spatialWidth, disableChannelsIfRgbDetected, shouldShowRemoveLayerButton } = props;
225174
+ const { layer, name: name2, loader: loader2, theme, handleLayerRemove, handleLayerChange, shouldShowTransparentColor, shouldShowDomain, shouldShowColormap, ChannelController, setViewState, disable3d, setImageLayerCallback, setAreLayerChannelsLoading, areLayerChannelsLoading, disabled, spatialHeight, spatialWidth, photometricInterpretation, shouldShowRemoveLayerButton } = props;
225007
225175
  const { colormap, opacity: opacity2, channels: channels2, transparentColor, renderingMode, xSlice, ySlice, zSlice, resolution, use3d, modelMatrix: modelMatrix2 } = layer;
225008
225176
  const channelRef = useRef(channels2);
225009
225177
  useEffect(() => {
@@ -225218,7 +225386,7 @@ function LayerController$1(props) {
225218
225386
  handleColormapChange: setColormap,
225219
225387
  handleGlobalChannelsSelectionChange,
225220
225388
  handleTransparentColorChange: setTransparentColor,
225221
- disableChannelsIfRgbDetected: isRgb(loader2, channels2) && disableChannelsIfRgbDetected,
225389
+ disableChannelsIfRgbDetected: photometricInterpretation === "RGB",
225222
225390
  handleDomainChange,
225223
225391
  shouldShowTransparentColor,
225224
225392
  shouldShowDomain,
@@ -225234,7 +225402,7 @@ function LayerController$1(props) {
225234
225402
  spatialHeight,
225235
225403
  spatialWidth,
225236
225404
  modelMatrix: modelMatrix2
225237
- }), isRgb(loader2, channels2) && disableChannelsIfRgbDetected ? null : channelControllers, isRgb(loader2, channels2) && disableChannelsIfRgbDetected ? null : jsxRuntimeExports.jsx(Button$1, { disabled: channels2.length === MAX_CHANNELS$1, onClick: handleChannelAdd, fullWidth: true, variant: "outlined", style: buttonStyles, startIcon: jsxRuntimeExports.jsx(AddIcon, {}), size: "small", children: "Add Channel" })] });
225405
+ }), photometricInterpretation === "RGB" ? null : channelControllers, photometricInterpretation === "RGB" ? null : jsxRuntimeExports.jsx(Button$1, { disabled: channels2.length === MAX_CHANNELS$1, onClick: handleChannelAdd, fullWidth: true, variant: "outlined", style: buttonStyles, startIcon: jsxRuntimeExports.jsx(AddIcon, {}), size: "small", children: "Add Channel" })] });
225238
225406
  return jsxRuntimeExports.jsxs(Accordion$1, { className: controllerSectionClasses.layerControllerRoot, onChange: (e3, expanded) => {
225239
225407
  var _a4, _b3, _c3;
225240
225408
  return !disabled && setIsExpanded(expanded && ((_c3 = (_b3 = (_a4 = e3 == null ? void 0 : e3.target) == null ? void 0 : _a4.attributes) == null ? void 0 : _b3.role) == null ? void 0 : _c3.value) === "presentation");
@@ -225311,6 +225479,7 @@ const LayerControllerMemoized = React__default.memo(forwardRef((props, ref2) =>
225311
225479
  setAreLoadingImageChannels,
225312
225480
  handleRasterLayerChange,
225313
225481
  handleRasterLayerRemove,
225482
+ photometricInterpretation,
225314
225483
  obsSegmentationsType,
225315
225484
  segmentationLayerLoaders,
225316
225485
  segmentationLayerMeta,
@@ -225432,6 +225601,7 @@ const LayerControllerMemoized = React__default.memo(forwardRef((props, ref2) =>
225432
225601
  disable3d: globalDisable3d || (disable3d || []).indexOf(layerMeta.name) >= 0 || typeof layerIs3DIndex === "number" && layerIs3DIndex !== -1 && layerIs3DIndex !== i2,
225433
225602
  disabled: typeof layerIs3DIndex === "number" && layerIs3DIndex !== -1 && layerIs3DIndex !== i2,
225434
225603
  disableChannelsIfRgbDetected,
225604
+ photometricInterpretation,
225435
225605
  imageLayerCallbacks,
225436
225606
  setImageLayerCallback,
225437
225607
  setViewState: ({ zoom: newZoom, target: target2, rotationX: newRotationX, rotationOrbit: newRotationOrbit }) => {
@@ -225455,7 +225625,7 @@ const LayerControllerMemoized = React__default.memo(forwardRef((props, ref2) =>
225455
225625
  function LayerControllerSubscriber$1(props) {
225456
225626
  const { coordinationScopes, closeButtonVisible, downloadButtonVisible, removeGridComponent, theme, title: title2 = "Spatial Layers", disable3d, globalDisable3d, disableChannelsIfRgbDetected, enableLayerButtonsWithOneLayer, helpText = ViewHelpMapping.LAYER_CONTROLLER } = props;
225457
225627
  const loaders = useLoaders();
225458
- const [{ dataset, obsType, spatialImageLayer: rasterLayers, spatialSegmentationLayer: cellsLayer, spatialPointLayer: moleculesLayer }, { setSpatialImageLayer: setRasterLayers, setSpatialSegmentationLayer: setCellsLayer, setSpatialPointLayer: setMoleculesLayer, setSpatialTargetX: setTargetX, setSpatialTargetY: setTargetY, setSpatialTargetZ: setTargetZ, setSpatialRotationX: setRotationX, setSpatialRotationOrbit: setRotationOrbit, setSpatialZoom: setZoom }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType$1.LAYER_CONTROLLER], coordinationScopes);
225628
+ const [{ dataset, obsType, spatialImageLayer: rasterLayers, spatialSegmentationLayer: cellsLayer, spatialPointLayer: moleculesLayer, photometricInterpretation: photometricInterpretationFromCoordination }, { setSpatialImageLayer: setRasterLayers, setSpatialSegmentationLayer: setCellsLayer, setSpatialPointLayer: setMoleculesLayer, setSpatialTargetX: setTargetX, setSpatialTargetY: setTargetY, setSpatialTargetZ: setTargetZ, setSpatialRotationX: setRotationX, setSpatialRotationOrbit: setRotationOrbit, setSpatialZoom: setZoom }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType$1.LAYER_CONTROLLER], coordinationScopes);
225459
225629
  const [{ imageLayerCallbacks, areLoadingImageChannels, segmentationLayerCallbacks, areLoadingSegmentationChannels }, { setImageLayerCallbacks, setAreLoadingImageChannels, setSegmentationLayerCallbacks, setAreLoadingSegmentationChannels }] = useAuxiliaryCoordination(COMPONENT_COORDINATION_TYPES.layerController, coordinationScopes);
225460
225630
  const [spatialLayout] = useComponentLayout("spatial", ["spatialImageLayer"], coordinationScopes);
225461
225631
  const layerControllerRef = useRef();
@@ -225464,12 +225634,13 @@ function LayerControllerSubscriber$1(props) {
225464
225634
  const [obsLocationsData, obsLocationsStatus] = useObsLocationsData(loaders, dataset, false, { setSpatialPointLayer: setMoleculesLayer }, { spatialPointLayer: moleculesLayer }, {});
225465
225635
  const [{ obsSegmentations, obsSegmentationsType }, obsSegmentationsStatus] = useObsSegmentationsData(loaders, dataset, false, { setSpatialSegmentationLayer: setCellsLayer }, { spatialSegmentationLayer: cellsLayer }, {});
225466
225636
  const [{ image: image2 }, imageStatus] = useImageData(loaders, dataset, false, { setSpatialImageLayer: setRasterLayers }, { spatialImageLayer: rasterLayers }, {});
225467
- const { loaders: imageLayerLoaders, meta: imageLayerMeta } = image2 || {};
225637
+ const { loaders: imageLayerLoaders, meta: imageLayerMeta, instance: instance2 } = image2 || {};
225468
225638
  const isReady = useReady([
225469
225639
  obsLocationsStatus,
225470
225640
  obsSegmentationsStatus,
225471
225641
  imageStatus
225472
225642
  ]);
225643
+ const photometricInterpretation = photometricInterpretationFromCoordination ?? (instance2 == null ? void 0 : instance2.getPhotometricInterpretation());
225473
225644
  const segmentationLayerLoaders = obsSegmentations && obsSegmentationsType === "bitmask" ? obsSegmentations.loaders : null;
225474
225645
  const segmentationLayerMeta = obsSegmentations && obsSegmentationsType === "bitmask" ? obsSegmentations.meta : null;
225475
225646
  const handleImageAdd = useCallback(async (index2) => {
@@ -225531,6 +225702,7 @@ function LayerControllerSubscriber$1(props) {
225531
225702
  setAreLoadingImageChannels,
225532
225703
  handleRasterLayerChange,
225533
225704
  handleRasterLayerRemove,
225705
+ photometricInterpretation,
225534
225706
  obsSegmentationsType,
225535
225707
  segmentationLayerLoaders,
225536
225708
  segmentationLayerMeta,
@@ -229349,7 +229521,7 @@ const useStyles$6 = makeStyles((theme) => ({
229349
229521
  }));
229350
229522
  register({ dataFetcher: ZarrMultivecDataFetcher_default, config: ZarrMultivecDataFetcher_default.config }, { pluginType: "dataFetcher" });
229351
229523
  const LazyHiGlassComponent = React__default.lazy(async () => {
229352
- const { HiGlassComponent } = await import("./higlass-0bd691db.js");
229524
+ const { HiGlassComponent } = await import("./higlass-a114d38b.js");
229353
229525
  return { default: HiGlassComponent };
229354
229526
  });
229355
229527
  const HG_SIZE = 800;
@@ -232297,7 +232469,7 @@ const useStyles$5 = makeStyles(() => ({
232297
232469
  }
232298
232470
  }));
232299
232471
  const LazyReactNeuroglancer = React__default.lazy(async () => {
232300
- const ReactNeuroglancer = await import("./index-c358749f.js").then((n3) => n3.i);
232472
+ const ReactNeuroglancer = await import("./index-9c4bd1c8.js").then((n3) => n3.i);
232301
232473
  return ReactNeuroglancer;
232302
232474
  });
232303
232475
  function createWorker() {
@@ -232320,16 +232492,20 @@ function NeuroglancerSubscriber(props) {
232320
232492
  const { closeButtonVisible, downloadButtonVisible, removeGridComponent, theme, title: title2 = "Neuroglancer", viewerState: viewerStateInitial = null, helpText = ViewHelpMapping.NEUROGLANCER } = props;
232321
232493
  return jsxRuntimeExports.jsx(TitleInfo, { title: title2, helpText, isSpatial: true, theme, closeButtonVisible, downloadButtonVisible, removeGridComponent, isReady: true, children: viewerStateInitial && jsxRuntimeExports.jsx(Neuroglancer, { viewerState: viewerStateInitial }) });
232322
232494
  }
232495
+ const FEATURE_AGGREGATION_STRATEGIES = ["first", "last", "sum", "mean"];
232323
232496
  function CellSetExpressionPlotOptions(props) {
232324
- const { featureValueTransform, setFeatureValueTransform, featureValueTransformCoefficient, setFeatureValueTransformCoefficient, transformOptions, featureValuePositivityThreshold, setFeatureValuePositivityThreshold, featureValueColormap, setFeatureValueColormap } = props;
232497
+ const { featureValueTransform, setFeatureValueTransform, featureValueTransformCoefficient, setFeatureValueTransformCoefficient, transformOptions, featureValuePositivityThreshold, setFeatureValuePositivityThreshold, featureValueColormap, setFeatureValueColormap, featureAggregationStrategy, setFeatureAggregationStrategy } = props;
232325
232498
  const cellSetExpressionPlotOptionsId = $bdb11010cef70236$export$f680877a34711e37();
232326
232499
  const classes = usePlotOptionsStyles();
232327
232500
  function handleFeatureValueColormapChange(event2) {
232328
232501
  setFeatureValueColormap(event2.target.value);
232329
232502
  }
232330
- const handleTransformChange = (event2) => {
232503
+ function handleTransformChange(event2) {
232331
232504
  setFeatureValueTransform(event2.target.value === "" ? null : event2.target.value);
232332
- };
232505
+ }
232506
+ function handleFeatureAggregationStrategyChange(event2) {
232507
+ setFeatureAggregationStrategy(event2.target.value);
232508
+ }
232333
232509
  function handlePositivityThresholdChange(event2, value2) {
232334
232510
  setFeatureValuePositivityThreshold(value2);
232335
232511
  }
@@ -232351,7 +232527,9 @@ function CellSetExpressionPlotOptions(props) {
232351
232527
  id: `cellset-expression-transform-select-${cellSetExpressionPlotOptionsId}`
232352
232528
  }, children: transformOptions.map((opt) => jsxRuntimeExports.jsx("option", { value: opt.value === null ? "" : opt.value, children: opt.name }, opt.name)) }) })] }), jsxRuntimeExports.jsxs(TableRow$1, { children: [jsxRuntimeExports.jsx(TableCell$1, { className: classes.labelCell, variant: "head", scope: "row", children: jsxRuntimeExports.jsx("label", { htmlFor: `cellset-expression-transform-coeff-${cellSetExpressionPlotOptionsId}`, children: "Transform Coefficient" }) }), jsxRuntimeExports.jsx(TableCell$1, { className: classes.inputCell, variant: "body", children: jsxRuntimeExports.jsx(TextField$1, { label: "Transform Coefficient", type: "number", onChange: handleTransformCoefficientChange, value: featureValueTransformCoefficient, InputLabelProps: {
232353
232529
  shrink: true
232354
- }, id: `cellset-expression-transform-coeff-${cellSetExpressionPlotOptionsId}` }) })] }), setFeatureValuePositivityThreshold ? jsxRuntimeExports.jsxs(TableRow$1, { children: [jsxRuntimeExports.jsx(TableCell$1, { className: classes.labelCell, children: "Positivity Threshold" }), jsxRuntimeExports.jsx(TableCell$1, { className: classes.inputCell, children: jsxRuntimeExports.jsx(Slider$1, { classes: { root: classes.slider, valueLabel: classes.sliderValueLabel }, value: featureValuePositivityThreshold, onChange: handlePositivityThresholdChange, "aria-labelledby": "pos-threshold-slider", valueLabelDisplay: "auto", step: 1, min: 0, max: 100 }) })] }, "transform-coefficient-option-row") : null] });
232530
+ }, id: `cellset-expression-transform-coeff-${cellSetExpressionPlotOptionsId}` }) })] }), setFeatureAggregationStrategy ? jsxRuntimeExports.jsxs(TableRow$1, { children: [jsxRuntimeExports.jsx(TableCell$1, { className: classes.labelCell, variant: "head", scope: "row", children: jsxRuntimeExports.jsx("label", { htmlFor: `feature-aggregation-strategy-${cellSetExpressionPlotOptionsId}`, children: "Feature Aggregation Strategy" }) }), jsxRuntimeExports.jsx(TableCell$1, { className: classes.inputCell, variant: "body", children: jsxRuntimeExports.jsx(OptionSelect, { className: classes.select, value: featureAggregationStrategy ?? "first", onChange: handleFeatureAggregationStrategyChange, inputProps: {
232531
+ id: `feature-aggregation-strategy-${cellSetExpressionPlotOptionsId}`
232532
+ }, children: FEATURE_AGGREGATION_STRATEGIES.map((opt) => jsxRuntimeExports.jsx("option", { value: opt, children: capitalize$2(opt) }, opt)) }) })] }) : null, setFeatureValuePositivityThreshold ? jsxRuntimeExports.jsxs(TableRow$1, { children: [jsxRuntimeExports.jsx(TableCell$1, { className: classes.labelCell, children: "Positivity Threshold" }), jsxRuntimeExports.jsx(TableCell$1, { className: classes.inputCell, children: jsxRuntimeExports.jsx(Slider$1, { classes: { root: classes.slider, valueLabel: classes.sliderValueLabel }, value: featureValuePositivityThreshold, onChange: handlePositivityThresholdChange, "aria-labelledby": "pos-threshold-slider", valueLabelDisplay: "auto", step: 1, min: 0, max: 100 }) })] }, "transform-coefficient-option-row") : null] });
232355
232533
  }
232356
232534
  function bandSpace$1(count2, paddingInner2, paddingOuter2) {
232357
232535
  var space2 = count2 - paddingInner2 + paddingOuter2 * 2;
@@ -237499,12 +237677,35 @@ function histogramStratifiedExpressionData(summarizedResult, binCount, yMinProp)
237499
237677
  // d3.scaleLinear without a range set
237500
237678
  };
237501
237679
  }
237502
- function useExpressionByCellSet(sampleEdges, sampleSets, sampleSetSelection, expressionData, obsIndex, cellSets, additionalCellSets, geneSelection, cellSetSelection, cellSetColor, featureValueTransform, featureValueTransformCoefficient, theme, yMinProp) {
237680
+ const DEFAULT_FEATURE_AGGREGATION_STRATEGY = "first";
237681
+ function featureSummary(geneSelection, featureAggregationStrategy) {
237682
+ if (featureAggregationStrategy === "first") {
237683
+ return geneSelection == null ? void 0 : geneSelection[0];
237684
+ }
237685
+ if (featureAggregationStrategy === "last") {
237686
+ return geneSelection == null ? void 0 : geneSelection.at(-1);
237687
+ }
237688
+ if (typeof featureAggregationStrategy === "number") {
237689
+ const i2 = featureAggregationStrategy;
237690
+ return geneSelection == null ? void 0 : geneSelection[i2];
237691
+ }
237692
+ if (featureAggregationStrategy === "sum") {
237693
+ return geneSelection == null ? void 0 : geneSelection.join(" + ");
237694
+ }
237695
+ if (featureAggregationStrategy === "mean") {
237696
+ return `Mean of ${geneSelection == null ? void 0 : geneSelection.join(", ")}`;
237697
+ }
237698
+ if (featureAggregationStrategy === "difference") {
237699
+ return geneSelection == null ? void 0 : geneSelection.join(" - ");
237700
+ }
237701
+ return "";
237702
+ }
237703
+ function useExpressionByCellSet(sampleEdges, sampleSets, sampleSetSelection, expressionData, obsIndex, cellSets, additionalCellSets, geneSelection, cellSetSelection, cellSetColor, featureValueTransform, featureValueTransformCoefficient, theme, yMinProp, featureAggregationStrategy) {
237503
237704
  const mergedCellSets = useMemo(() => mergeObsSets(cellSets, additionalCellSets), [cellSets, additionalCellSets]);
237504
237705
  const [expressionArr, expressionMax] = useMemo(() => {
237505
237706
  const [stratifiedData, exprMax] = stratifyExpressionData(sampleEdges, sampleSets, sampleSetSelection, expressionData, obsIndex, mergedCellSets, geneSelection, cellSetSelection, cellSetColor, featureValueTransform, featureValueTransformCoefficient);
237506
237707
  if (stratifiedData) {
237507
- const aggregateData = aggregateStratifiedExpressionData(stratifiedData, geneSelection);
237708
+ const aggregateData = aggregateStratifiedExpressionData(stratifiedData, geneSelection, featureAggregationStrategy);
237508
237709
  const summarizedData = summarizeStratifiedExpressionData(aggregateData, true);
237509
237710
  const histogramData = histogramStratifiedExpressionData(summarizedData, 16, yMinProp);
237510
237711
  return [histogramData, exprMax];
@@ -237523,7 +237724,8 @@ function useExpressionByCellSet(sampleEdges, sampleSets, sampleSetSelection, exp
237523
237724
  yMinProp,
237524
237725
  sampleEdges,
237525
237726
  sampleSets,
237526
- sampleSetSelection
237727
+ sampleSetSelection,
237728
+ featureAggregationStrategy
237527
237729
  ]);
237528
237730
  const setArr = useMemo(() => mergedCellSets && cellSetSelection && cellSetColor ? treeToSetSizesBySetNames(mergedCellSets, cellSetSelection, cellSetSelection, cellSetColor, theme) : [], [mergedCellSets, cellSetSelection, cellSetColor, theme]);
237529
237731
  return [expressionArr, setArr, expressionMax];
@@ -237533,7 +237735,7 @@ function CellSetExpressionPlotSubscriber(props) {
237533
237735
  const { coordinationScopes, closeButtonVisible, downloadButtonVisible, removeGridComponent, theme, title: title2, xAxisTitle, jitter: jitter2 = false, yMin = null, yUnits = null, helpText = ViewHelpMapping.OBS_SET_FEATURE_VALUE_DISTRIBUTION } = props;
237534
237736
  const classes = useStyles$4();
237535
237737
  const loaders = useLoaders();
237536
- 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$1.OBS_SET_FEATURE_VALUE_DISTRIBUTION], coordinationScopes);
237738
+ 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$1.OBS_SET_FEATURE_VALUE_DISTRIBUTION], coordinationScopes);
237537
237739
  const [width2, height2, containerRef] = useGridItemSize();
237538
237740
  const transformOptions = VALUE_TRANSFORM_OPTIONS;
237539
237741
  const [expressionData, loadedFeatureSelection, featureSelectionStatus] = useFeatureSelection(loaders, dataset, false, geneSelection, { obsType, featureType, featureValueType });
@@ -237559,11 +237761,18 @@ function CellSetExpressionPlotSubscriber(props) {
237559
237761
  sampleSetsUrls,
237560
237762
  sampleEdgesUrls
237561
237763
  ]);
237562
- const [histogramData, setArr, exprMax] = useExpressionByCellSet(sampleEdges, sampleSets, sampleSetSelection, expressionData, obsIndex, cellSets, additionalCellSets, geneSelection, cellSetSelection, cellSetColor, featureValueTransform, featureValueTransformCoefficient, theme, yMin);
237563
- const firstGeneSelected = geneSelection && geneSelection.length >= 1 ? (featureLabelsMap == null ? void 0 : featureLabelsMap.get(geneSelection[0])) || (featureLabelsMap == null ? void 0 : featureLabelsMap.get(cleanFeatureId(geneSelection[0]))) || geneSelection[0] : null;
237764
+ const featureAggregationStrategyToUse = featureAggregationStrategy ?? DEFAULT_FEATURE_AGGREGATION_STRATEGY;
237765
+ const [histogramData, setArr, exprMax] = useExpressionByCellSet(sampleEdges, sampleSets, sampleSetSelection, expressionData, obsIndex, cellSets, additionalCellSets, geneSelection, cellSetSelection, cellSetColor, featureValueTransform, featureValueTransformCoefficient, theme, yMin, featureAggregationStrategyToUse);
237766
+ const featureSuffix = useMemo(() => {
237767
+ const cleanedGeneSelection = geneSelection == null ? void 0 : geneSelection.map((geneName) => (featureLabelsMap == null ? void 0 : featureLabelsMap.get(geneName)) || (featureLabelsMap == null ? void 0 : featureLabelsMap.get(cleanFeatureId(geneName))) || geneName);
237768
+ if (Array.isArray(cleanedGeneSelection)) {
237769
+ return featureSummary(cleanedGeneSelection, featureAggregationStrategyToUse);
237770
+ }
237771
+ return null;
237772
+ }, [geneSelection, featureAggregationStrategyToUse]);
237564
237773
  const selectedTransformName = (_a3 = transformOptions.find((o2) => o2.value === featureValueTransform)) == null ? void 0 : _a3.name;
237565
- const titleSuffix = firstGeneSelected ? ` (${firstGeneSelected})` : "";
237566
- return jsxRuntimeExports.jsx(TitleInfo, { title: title2 ? `${title2}${titleSuffix}` : `Expression by ${capitalize$2(obsType)} Set${titleSuffix}`, closeButtonVisible, downloadButtonVisible, removeGridComponent, urls: urls2, theme, isReady, helpText, options: jsxRuntimeExports.jsx(CellSetExpressionPlotOptions, { featureValueTransform, setFeatureValueTransform, featureValueTransformCoefficient, setFeatureValueTransformCoefficient, transformOptions }), children: jsxRuntimeExports.jsx("div", { ref: containerRef, className: classes.vegaContainer, children: histogramData ? jsxRuntimeExports.jsx(CellSetExpressionPlot, { yMin, yUnits, jitter: jitter2, obsSetSelection: cellSetSelection, obsSetColor: cellSetColor, sampleSetSelection, sampleSetColor, colors: setArr, data: histogramData, exprMax, theme, width: width2, height: height2, obsType, featureType, featureValueType, featureValueTransformName: selectedTransformName, xAxisTitle }) : jsxRuntimeExports.jsxs("span", { children: ["Select a ", featureType, "."] }) }) });
237774
+ const titleSuffix = featureSuffix ? ` (${featureSuffix})` : "";
237775
+ return jsxRuntimeExports.jsx(TitleInfo, { title: title2 ? `${title2}${titleSuffix}` : `Expression by ${capitalize$2(obsType)} Set${titleSuffix}`, closeButtonVisible, downloadButtonVisible, removeGridComponent, urls: urls2, theme, isReady, helpText, options: jsxRuntimeExports.jsx(CellSetExpressionPlotOptions, { featureValueTransform, setFeatureValueTransform, featureValueTransformCoefficient, setFeatureValueTransformCoefficient, transformOptions, featureAggregationStrategy, setFeatureAggregationStrategy }), children: jsxRuntimeExports.jsx("div", { ref: containerRef, className: classes.vegaContainer, children: histogramData ? jsxRuntimeExports.jsx(CellSetExpressionPlot, { yMin, yUnits, jitter: jitter2, obsSetSelection: cellSetSelection, obsSetColor: cellSetColor, sampleSetSelection, sampleSetColor, colors: setArr, data: histogramData, exprMax, theme, width: width2, height: height2, obsType, featureType, featureValueType, featureValueTransformName: selectedTransformName, xAxisTitle }) : jsxRuntimeExports.jsxs("span", { children: ["Select a ", featureType, "."] }) }) });
237567
237776
  }
237568
237777
  /*! *****************************************************************************
237569
237778
  Copyright (c) Microsoft Corporation.
@@ -289528,7 +289737,26 @@ function ExpressionHistogramSubscriber(props) {
289528
289737
  return jsxRuntimeExports.jsx(TitleInfo, { title: `Histogram${firstGeneSelected ? ` (${firstGeneSelected})` : ""}`, closeButtonVisible, downloadButtonVisible, removeGridComponent, urls: urls2, theme, isReady, helpText, children: jsxRuntimeExports.jsx("div", { ref: containerRef, className: classes.vegaContainer, children: jsxRuntimeExports.jsx(ExpressionHistogram, { geneSelection, obsType, featureType, featureValueType, onSelect, data: data2, theme, width: width2, height: height2 }) }) });
289529
289738
  }
289530
289739
  function DotPlot(props) {
289531
- const { isStratified, transpose: transpose2, data: rawData, theme, width: width2, height: height2, marginRight, marginBottom, obsType, sampleType, keyLength = 36, featureType, featureValueType, featureValueTransformName, featureValueColormap, obsSetSelection, obsSetColor } = props;
289740
+ const {
289741
+ isStratified,
289742
+ transpose: transpose2,
289743
+ data: rawData,
289744
+ theme,
289745
+ width: width2,
289746
+ height: height2,
289747
+ marginRight,
289748
+ marginBottom,
289749
+ obsType,
289750
+ sampleType,
289751
+ keyLength = 36,
289752
+ featureType,
289753
+ featureValueType,
289754
+ featureValueTransformName,
289755
+ // TODO: re-enable featureValueColormap coordination
289756
+ // featureValueColormap,
289757
+ obsSetSelection,
289758
+ obsSetColor
289759
+ } = props;
289532
289760
  const vegaContainerRef = useRef();
289533
289761
  const data2 = rawData.map((d) => ({
289534
289762
  ...d,
@@ -289587,7 +289815,8 @@ function DotPlot(props) {
289587
289815
  type: "quantitative",
289588
289816
  title: meanTransform,
289589
289817
  scale: {
289590
- scheme: featureValueColormap
289818
+ // scheme: featureValueColormap,
289819
+ scheme: "greys"
289591
289820
  },
289592
289821
  legend: {
289593
289822
  direction: "horizontal",
@@ -290090,8 +290319,6 @@ function TreemapSubscriber(props) {
290090
290319
  ]);
290091
290320
  const mergedObsSets = useMemo(() => mergeObsSets(obsSets, additionalObsSets), [obsSets, additionalObsSets]);
290092
290321
  const mergedSampleSets = useMemo(() => mergeObsSets(sampleSets, null), [sampleSets]);
290093
- const obsCount = (obsIndex == null ? void 0 : obsIndex.length) || 0;
290094
- const sampleCount = (sampleIndex == null ? void 0 : sampleIndex.length) || 0;
290095
290322
  const [obsCounts, sampleCounts] = useMemo(() => {
290096
290323
  var _a3, _b3;
290097
290324
  const obsResult = new InternMap$1([], JSON.stringify);
@@ -290112,7 +290339,7 @@ function TreemapSubscriber(props) {
290112
290339
  const sampleSetSize = (_a4 = sampleSetSizes == null ? void 0 : sampleSetSizes.find((d) => isEqual$5(d.setNamePath, sampleSetKey))) == null ? void 0 : _a4.size;
290113
290340
  sampleResult.set(sampleSetKey, sampleSetSize || 0);
290114
290341
  });
290115
- if (mergedObsSets && obsSetSelection) {
290342
+ if (mergedObsSets && obsSetSelection && obsIndex) {
290116
290343
  const sampleIdToSetMap = sampleSets && sampleSetSelection ? treeToSelectedSetMap(sampleSets, sampleSetSelection) : null;
290117
290344
  const cellIdToSetMap = treeToSelectedSetMap(mergedObsSets, obsSetSelection);
290118
290345
  for (let i2 = 0; i2 < obsIndex.length; i2 += 1) {
@@ -290140,13 +290367,20 @@ function TreemapSubscriber(props) {
290140
290367
  mergedObsSets,
290141
290368
  obsSetSelection,
290142
290369
  mergedSampleSets,
290143
- sampleSetSelection
290370
+ sampleSetSelection,
290371
+ obsIndex
290144
290372
  // TODO: consider filtering-related coordination values
290145
290373
  ]);
290374
+ const totalObsCount = (obsIndex == null ? void 0 : obsIndex.length) || 0;
290375
+ const totalSampleCount = (sampleIndex == null ? void 0 : sampleIndex.length) || 0;
290376
+ const selectedObsCount = obsCounts.reduce((a2, h2) => a2 + h2.value, 0);
290377
+ const selectedSampleCount = sampleCounts.reduce((a2, h2) => a2 + h2.value, 0);
290378
+ const unselectedObsCount = totalObsCount - selectedObsCount;
290379
+ const unselectedSampleCount = totalSampleCount - selectedSampleCount;
290146
290380
  const onNodeClick = useCallback((obsSetPath2) => {
290147
290381
  setObsSetSelection([obsSetPath2]);
290148
290382
  }, [setObsSetSelection]);
290149
- return jsxRuntimeExports.jsx(TitleInfo, { title: `Treemap of ${capitalize$2(pluralize(obsType, 2))}`, info: `${commaNumber(obsCount)} ${pluralize(obsType, obsCount)} from ${commaNumber(sampleCount)} ${pluralize(sampleType, sampleCount)}`, removeGridComponent, urls: urls2, theme, isReady, helpText, options: jsxRuntimeExports.jsx(TreemapOptions, { obsType, sampleType, obsColorEncoding, setObsColorEncoding, hierarchyLevels: hierarchyLevels || DEFAULT_HIERARCHY_LEVELS, setHierarchyLevels }), children: jsxRuntimeExports.jsx("div", { ref: containerRef, className: classes.vegaContainer, children: jsxRuntimeExports.jsx(Treemap, { obsCounts, sampleCounts, obsColorEncoding, hierarchyLevels: hierarchyLevels || DEFAULT_HIERARCHY_LEVELS, theme, width: width2, height: height2, obsType, sampleType, obsSetColor, sampleSetColor, obsSetSelection, sampleSetSelection, onNodeClick }) }) });
290383
+ return jsxRuntimeExports.jsxs(TitleInfo, { title: `Treemap of ${capitalize$2(pluralize(obsType, 2))}`, info: `${commaNumber(selectedObsCount)} ${pluralize(obsType, selectedObsCount)} from ${commaNumber(selectedSampleCount)} ${pluralize(sampleType, selectedSampleCount)}`, removeGridComponent, urls: urls2, theme, isReady, helpText, withPadding: false, options: jsxRuntimeExports.jsx(TreemapOptions, { obsType, sampleType, obsColorEncoding, setObsColorEncoding, hierarchyLevels: hierarchyLevels || DEFAULT_HIERARCHY_LEVELS, setHierarchyLevels }), children: [jsxRuntimeExports.jsx("div", { ref: containerRef, className: classes.vegaContainer, children: jsxRuntimeExports.jsx(Treemap, { obsCounts, sampleCounts, obsColorEncoding, hierarchyLevels: hierarchyLevels || DEFAULT_HIERARCHY_LEVELS, theme, width: width2, height: Math.max(height2 * (selectedObsCount / totalObsCount), 40), obsType, sampleType, obsSetColor, sampleSetColor, obsSetSelection, sampleSetSelection, onNodeClick }) }), jsxRuntimeExports.jsx("div", { style: { position: "absolute", right: "2px", bottom: "2px", fontSize: "10px" }, children: unselectedObsCount > 0 ? jsxRuntimeExports.jsx("span", { children: `${commaNumber(unselectedObsCount)} ${pluralize(obsType, unselectedObsCount)} from ${commaNumber(unselectedSampleCount)} ${pluralize(sampleType, unselectedSampleCount)} currently omitted` }) : null })] });
290150
290384
  }
290151
290385
  function VolcanoPlot(props) {
290152
290386
  const { theme, width: width2, height: height2, obsType, featureType, obsSetsColumnNameMappingReversed, sampleSetsColumnNameMappingReversed, sampleSetSelection, obsSetSelection, obsSetColor, sampleSetColor, data: data2, marginTop = 5, marginRight = 5, marginLeft = 50, marginBottom = 50, onFeatureClick, featurePointSignificanceThreshold, featurePointFoldChangeThreshold, featureLabelSignificanceThreshold, featureLabelFoldChangeThreshold } = props;
@@ -290303,27 +290537,28 @@ function VolcanoPlotSubscriber(props) {
290303
290537
  }, [setFeatureSelection]);
290304
290538
  return jsxRuntimeExports.jsx(TitleInfo, { title: title2, removeGridComponent, theme, isReady, helpText, options: jsxRuntimeExports.jsx(VolcanoPlotOptions, { obsType, featureType, featurePointSignificanceThreshold, featurePointFoldChangeThreshold, featureLabelSignificanceThreshold, featureLabelFoldChangeThreshold, setFeaturePointSignificanceThreshold, setFeaturePointFoldChangeThreshold, setFeatureLabelSignificanceThreshold, setFeatureLabelFoldChangeThreshold }), children: jsxRuntimeExports.jsx("div", { ref: containerRef, className: classes.vegaContainer, children: featureStats ? jsxRuntimeExports.jsx(VolcanoPlot, { theme, width: width2, height: height2, obsType, featureType, obsSetsColumnNameMapping, obsSetsColumnNameMappingReversed, sampleSetsColumnNameMapping, sampleSetsColumnNameMappingReversed, sampleSetSelection, obsSetSelection, obsSetColor, sampleSetColor, data: featureStats, onFeatureClick, featurePointSignificanceThreshold, featurePointFoldChangeThreshold, featureLabelSignificanceThreshold, featureLabelFoldChangeThreshold }) : jsxRuntimeExports.jsxs("span", { children: ["Select at least one ", obsType, " set."] }) }) });
290305
290539
  }
290540
+ const MAX_BAR_SIZE = 40;
290306
290541
  function CellSetCompositionBarPlot(props) {
290307
- const { data: data2, theme, width: width2, height: height2, marginRight = 200, marginBottom = 120, keyLength = 36, obsType, onBarSelect, obsSetsColumnNameMappingReversed, sampleSetsColumnNameMappingReversed, sampleSetSelection, obsSetSelection, obsSetColor, sampleSetColor } = props;
290542
+ const { data: data2, theme, width: width2, height: heightProp, marginRight = 200, marginBottom = 60, keyLength = 36, obsType, onBarSelect, obsSetsColumnNameMappingReversed, sampleSetsColumnNameMappingReversed, sampleSetSelection, obsSetSelection, obsSetColor, sampleSetColor } = props;
290543
+ const height2 = Array.isArray(obsSetSelection) && (heightProp - marginBottom) / obsSetSelection.length >= MAX_BAR_SIZE ? MAX_BAR_SIZE * obsSetSelection.length + marginBottom : heightProp;
290308
290544
  const [obsSetColorScale, sampleSetColorScale] = useMemo(() => [
290309
290545
  getColorScale(obsSetSelection, obsSetColor, theme),
290310
290546
  getColorScale(sampleSetSelection, sampleSetColor, theme)
290311
290547
  ], [obsSetSelection, sampleSetSelection, sampleSetColor, obsSetColor, theme]);
290312
290548
  const computedData = useMemo(() => {
290313
- var _a3, _b3, _c3, _d3, _e3, _f3, _g3;
290549
+ var _a3, _b3, _c3, _d3, _e3, _f3;
290314
290550
  if (Array.isArray(data2) && data2.length === 1) {
290315
290551
  const { df, metadata: metadata2 } = data2[0];
290316
290552
  const referenceCellType = (_a3 = metadata2 == null ? void 0 : metadata2.analysis_params) == null ? void 0 : _a3.reference_cell_type;
290553
+ const covariateValue = (_b3 = metadata2 == null ? void 0 : metadata2.analysis_params) == null ? void 0 : _b3.covariate_value;
290317
290554
  const coordinationValues = metadata2 == null ? void 0 : metadata2.coordination_values;
290318
- const obsSetColumnName = (_c3 = (_b3 = coordinationValues == null ? void 0 : coordinationValues.obsSetSelection) == null ? void 0 : _b3[0]) == null ? void 0 : _c3[0];
290555
+ const obsSetColumnName = (_d3 = (_c3 = coordinationValues == null ? void 0 : coordinationValues.obsSetSelection) == null ? void 0 : _c3[0]) == null ? void 0 : _d3[0];
290319
290556
  const obsSetGroupName = obsSetsColumnNameMappingReversed == null ? void 0 : obsSetsColumnNameMappingReversed[obsSetColumnName];
290320
- const sampleSetColumnName = (_e3 = (_d3 = coordinationValues == null ? void 0 : coordinationValues.sampleSetFilter) == null ? void 0 : _d3[0]) == null ? void 0 : _e3[0];
290557
+ const sampleSetColumnName = (_f3 = (_e3 = coordinationValues == null ? void 0 : coordinationValues.sampleSetFilter) == null ? void 0 : _e3[0]) == null ? void 0 : _f3[0];
290321
290558
  const sampleSetGroupName = sampleSetsColumnNameMappingReversed == null ? void 0 : sampleSetsColumnNameMappingReversed[sampleSetColumnName];
290322
- const covariatePrefix = `${sampleSetColumnName}T.`;
290323
- const firstCovariateValue = (_g3 = (_f3 = df.covariate) == null ? void 0 : _f3[0]) == null ? void 0 : _g3.substring(covariatePrefix.length);
290324
- const firstCovariateSetPath = [sampleSetGroupName, firstCovariateValue];
290559
+ const covariateSetPath = [sampleSetGroupName, covariateValue];
290325
290560
  let shouldSwapFoldChangeDirection = false;
290326
- if (isEqual$5(firstCovariateSetPath, sampleSetSelection[0])) {
290561
+ if (isEqual$5(covariateSetPath, sampleSetSelection[0])) {
290327
290562
  shouldSwapFoldChangeDirection = true;
290328
290563
  }
290329
290564
  return df.obsSetId.map((obsSetId, i2) => {
@@ -290380,6 +290615,22 @@ function CellSetCompositionBarPlot(props) {
290380
290615
  domain: [true, false],
290381
290616
  range: [2, 0.5]
290382
290617
  };
290618
+ const xExtent = useMemo(() => {
290619
+ if (computedData) {
290620
+ const [min2, max2] = extent$2(computedData.map((d) => d.logFoldChange));
290621
+ const buffer2 = 1.05;
290622
+ const minAbs = Math.abs(min2) * buffer2;
290623
+ const maxAbs = Math.abs(max2) * buffer2;
290624
+ if (minAbs > maxAbs) {
290625
+ return [-minAbs, minAbs];
290626
+ }
290627
+ return [-maxAbs, maxAbs];
290628
+ }
290629
+ return void 0;
290630
+ }, [computedData]);
290631
+ const xScale = {
290632
+ domain: xExtent
290633
+ };
290383
290634
  const spec = {
290384
290635
  mark: { type: "bar", stroke: "black", cursor: "pointer" },
290385
290636
  params: [
@@ -290414,7 +290665,8 @@ function CellSetCompositionBarPlot(props) {
290414
290665
  // TODO: support using intercept+effect here based on user-selected options?
290415
290666
  field: "logFoldChange",
290416
290667
  type: "quantitative",
290417
- title: "Log fold-change"
290668
+ title: "Log fold-change",
290669
+ scale: xScale
290418
290670
  },
290419
290671
  color: {
290420
290672
  field: "key",
@@ -290430,7 +290682,8 @@ function CellSetCompositionBarPlot(props) {
290430
290682
  strokeWidth: {
290431
290683
  field: "isReferenceSet",
290432
290684
  type: "nominal",
290433
- scale: strokeWidthScale
290685
+ scale: strokeWidthScale,
290686
+ legend: null
290434
290687
  },
290435
290688
  tooltip: {
290436
290689
  field: "effectExpectedSample",
@@ -290489,7 +290742,7 @@ function CellSetCompositionBarPlotSubscriber(props) {
290489
290742
  return jsxRuntimeExports.jsx(TitleInfo, { title: `${capitalize$2(obsType)} Set Composition Analysis Plot`, removeGridComponent, theme, isReady, helpText, children: jsxRuntimeExports.jsx("div", { ref: containerRef, className: classes.vegaContainer, children: obsSetStats ? jsxRuntimeExports.jsx(CellSetCompositionBarPlot, { theme, width: width2, height: height2, obsType, obsSetsColumnNameMapping, obsSetsColumnNameMappingReversed, sampleSetsColumnNameMapping, sampleSetsColumnNameMappingReversed, sampleSetSelection, obsSetSelection, obsSetColor, sampleSetColor, data: obsSetStats, onBarSelect }) : jsxRuntimeExports.jsxs("span", { children: ["Select at least one ", obsType, " set and a pair of ", sampleType, " sets."] }) }) });
290490
290743
  }
290491
290744
  function FeatureSetEnrichmentBarPlot(props) {
290492
- const { data: data2, theme, width: width2, height: height2, marginRight = 200, marginBottom = 120, keyLength = 36, featureType, onBarSelect, obsSetsColumnNameMappingReversed, sampleSetsColumnNameMappingReversed, sampleSetSelection, obsSetSelection, obsSetColor, sampleSetColor, pValueThreshold } = props;
290745
+ const { data: data2, theme, width: width2, height: height2, marginRight = 300, marginBottom = 120, keyLength = 36, featureType, onBarSelect, obsSetsColumnNameMappingReversed, sampleSetsColumnNameMappingReversed, sampleSetSelection, obsSetSelection, obsSetColor, sampleSetColor, pValueThreshold } = props;
290493
290746
  const [obsSetColorScale, sampleSetColorScale] = useMemo(() => [
290494
290747
  getColorScale(obsSetSelection, obsSetColor, theme),
290495
290748
  getColorScale(sampleSetSelection, sampleSetColor, theme)
@@ -290534,7 +290787,7 @@ function FeatureSetEnrichmentBarPlot(props) {
290534
290787
  }
290535
290788
  return [...a2, h2];
290536
290789
  }, []);
290537
- const MAX_ROWS = 25;
290790
+ const MAX_ROWS = 50;
290538
290791
  result = result.slice(0, MAX_ROWS);
290539
290792
  return result;
290540
290793
  }
@@ -290565,7 +290818,7 @@ function FeatureSetEnrichmentBarPlot(props) {
290565
290818
  select: {
290566
290819
  type: "point",
290567
290820
  on: "click[event.shiftKey === false]",
290568
- fields: ["name"],
290821
+ fields: ["name", "term"],
290569
290822
  empty: "none"
290570
290823
  }
290571
290824
  },
@@ -290574,7 +290827,7 @@ function FeatureSetEnrichmentBarPlot(props) {
290574
290827
  select: {
290575
290828
  type: "point",
290576
290829
  on: "click[event.shiftKey]",
290577
- fields: ["name"],
290830
+ fields: ["name", "term"],
290578
290831
  empty: "none"
290579
290832
  }
290580
290833
  }
@@ -290621,10 +290874,11 @@ function FeatureSetEnrichmentBarPlot(props) {
290621
290874
  config: VEGA_THEMES[theme]
290622
290875
  };
290623
290876
  const handleSignal = (name2, value2) => {
290877
+ var _a3, _b3;
290624
290878
  if (name2 === "bar_select") {
290625
- onBarSelect(value2.obsSetPath);
290879
+ onBarSelect((_a3 = value2.name) == null ? void 0 : _a3[0], (_b3 = value2.term) == null ? void 0 : _b3[0]);
290626
290880
  } else if (name2 === "shift_bar_select") {
290627
- onBarSelect(value2.obsSetPath, true);
290881
+ onBarSelect(value2.name, value2.term, true);
290628
290882
  }
290629
290883
  };
290630
290884
  const signalListeners = { bar_select: handleSignal, shift_bar_select: handleSignal };
@@ -290642,7 +290896,7 @@ function FeatureSetEnrichmentBarPlotSubscriber(props) {
290642
290896
  const { coordinationScopes, removeGridComponent, theme, helpText = ViewHelpMapping.FEATURE_SET_ENRICHMENT_BAR_PLOT } = props;
290643
290897
  const classes = useStyles$4();
290644
290898
  const loaders = useLoaders();
290645
- useAsyncFunction(AsyncFunctionType.TRANSFORM_FEATURE);
290899
+ const transformFeature2 = useAsyncFunction(AsyncFunctionType.TRANSFORM_FEATURE);
290646
290900
  const [{ dataset, obsType, sampleType, featureType, featureValueType, obsFilter: cellFilter, obsHighlight: cellHighlight, obsSetSelection, obsSetColor, obsColorEncoding: cellColorEncoding, additionalObsSets: additionalCellSets, featurePointSignificanceThreshold, featurePointFoldChangeThreshold, featureLabelSignificanceThreshold, featureLabelFoldChangeThreshold, featureValueTransform, featureValueTransformCoefficient, gatingFeatureSelectionX, gatingFeatureSelectionY, featureSelection, sampleSetSelection, sampleSetColor }, { setObsFilter: setCellFilter, setObsSetSelection, setObsHighlight: setCellHighlight, setObsSetColor: setCellSetColor, setObsColorEncoding: setCellColorEncoding, setAdditionalObsSets: setAdditionalCellSets, setFeaturePointSignificanceThreshold, setFeaturePointFoldChangeThreshold, setFeatureLabelSignificanceThreshold, setFeatureLabelFoldChangeThreshold, setFeatureValueTransform, setFeatureValueTransformCoefficient, setGatingFeatureSelectionX, setGatingFeatureSelectionY, setFeatureSelection, setSampleSetSelection, setSampleSetColor }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType$1.FEATURE_SET_ENRICHMENT_BAR_PLOT], coordinationScopes);
290647
290901
  const [width2, height2, containerRef] = useGridItemSize();
290648
290902
  const obsSetsLoader = useMatchingLoader(loaders, dataset, DataType$3.OBS_SETS, { obsType });
@@ -290665,6 +290919,11 @@ function FeatureSetEnrichmentBarPlotSubscriber(props) {
290665
290919
  featureSetStatsStatus
290666
290920
  ]);
290667
290921
  const onBarSelect = useCallback(async (featureSetName, featureSetTerm, isShiftDown = false) => {
290922
+ const kgNode = { nodeType: "pathway", term: featureSetTerm };
290923
+ const targetFeatureType = featureType;
290924
+ const targetsInPathway = await transformFeature2(kgNode, targetFeatureType);
290925
+ const featureIds = targetsInPathway.filter((d, i2) => i2 < 10).map((d) => d.label);
290926
+ setFeatureSelection(featureIds);
290668
290927
  }, [setFeatureSelection]);
290669
290928
  return jsxRuntimeExports.jsx(TitleInfo, { title: `${capitalize$2(featureType)} Set Enrichment Plot`, removeGridComponent, theme, isReady, helpText, children: jsxRuntimeExports.jsx("div", { ref: containerRef, className: classes.vegaContainer, children: featureSetStats ? jsxRuntimeExports.jsx(FeatureSetEnrichmentBarPlot, { theme, width: width2, height: height2, obsType, featureType, obsSetsColumnNameMapping, obsSetsColumnNameMappingReversed, sampleSetsColumnNameMapping, sampleSetsColumnNameMappingReversed, sampleSetSelection, obsSetSelection, obsSetColor, sampleSetColor, data: featureSetStats, onBarSelect, pValueThreshold: 0.01 }) : jsxRuntimeExports.jsxs("span", { children: ["Select at least one ", obsType, " set."] }) }) });
290670
290929
  }
@@ -296346,79 +296605,88 @@ class MoleculesJsonAsObsLocationsLoader extends JsonLoader {
296346
296605
  }
296347
296606
  }
296348
296607
  async function initLoader(imageData) {
296349
- const { type: type2, url, metadata: metadata2, requestInit: requestInit2 } = imageData;
296350
- switch (type2) {
296351
- case "zarr": {
296352
- const { dimensions, isPyramid, transform: transform4 } = metadata2 || {};
296353
- const labels2 = dimensions.map((d) => d.field);
296354
- let source2;
296355
- const root2 = await zarrOpenRoot(url, null, { requestInit: requestInit2 });
296356
- if (isPyramid) {
296357
- const metadataUrl = `${url}${url.slice(-1) === "/" ? "" : "/"}.zmetadata`;
296358
- const response = await fetch(metadataUrl);
296359
- const { metadata: zarrMetadata } = await response.json();
296360
- const paths = Object.keys(zarrMetadata).filter((metaKey) => metaKey.includes(".zarray")).map((arrMetaKeys) => arrMetaKeys.slice(0, -7));
296361
- const data2 = await Promise.all(paths.map((path2) => open$1(root2.resolve(path2), { kind: "array" })));
296362
- const tileSize = guessTileSize(data2[0]);
296363
- source2 = data2.map((d) => new ZarritaPixelSource(createZarrArrayAdapter(d), labels2, tileSize));
296364
- } else {
296365
- const data2 = await open$1(root2, { kind: "array" });
296366
- source2 = new ZarritaPixelSource(createZarrArrayAdapter(data2), labels2);
296367
- }
296368
- return { data: source2, metadata: { dimensions, transform: transform4 }, channels: (dimensions.find((d) => d.field === "channel") || dimensions[0]).values };
296369
- }
296370
- case "ome-tiff": {
296371
- let loader2;
296372
- if (metadata2 && "omeTiffOffsetsUrl" in metadata2) {
296373
- const { omeTiffOffsetsUrl } = metadata2;
296374
- const res = await fetch(omeTiffOffsetsUrl, requestInit2 || {});
296375
- if (res.ok) {
296376
- const offsets2 = await res.json();
296377
- loader2 = await loadOmeTiff(url, {
296378
- offsets: offsets2,
296379
- headers: requestInit2 == null ? void 0 : requestInit2.headers
296380
- });
296608
+ try {
296609
+ const { type: type2, url, metadata: metadata2, requestInit: requestInit2 } = imageData;
296610
+ switch (type2) {
296611
+ case "zarr": {
296612
+ const { dimensions, isPyramid, transform: transform4 } = metadata2 || {};
296613
+ const labels2 = dimensions.map((d) => d.field);
296614
+ let source2;
296615
+ const root2 = await zarrOpenRoot(url, null, { requestInit: requestInit2 });
296616
+ if (isPyramid) {
296617
+ const metadataUrl = `${url}${url.slice(-1) === "/" ? "" : "/"}.zmetadata`;
296618
+ const response = await fetch(metadataUrl);
296619
+ if (!response.ok)
296620
+ throw new Error(`Failed to fetch metadata: ${response.status}`);
296621
+ const { metadata: zarrMetadata } = await response.json();
296622
+ const paths = Object.keys(zarrMetadata).filter((metaKey) => metaKey.includes(".zarray")).map((arrMetaKeys) => arrMetaKeys.slice(0, -7));
296623
+ const data2 = await Promise.all(paths.map((path2) => open$1(root2.resolve(path2), { kind: "array" })));
296624
+ const tileSize = guessTileSize(data2[0]);
296625
+ source2 = data2.map((d) => new ZarritaPixelSource(createZarrArrayAdapter(d), labels2, tileSize));
296381
296626
  } else {
296382
- throw new Error(`Offsets not found but provided: ${res.status} from ${res.url}`);
296627
+ const data2 = await open$1(root2, { kind: "array" });
296628
+ source2 = new ZarritaPixelSource(createZarrArrayAdapter(data2), labels2);
296383
296629
  }
296384
- } else {
296385
- loader2 = await loadOmeTiff(url, { headers: requestInit2 == null ? void 0 : requestInit2.headers });
296386
- }
296387
- const { Pixels: { Channels } } = loader2.metadata;
296388
- const channels2 = Array.isArray(Channels) ? Channels.map((channel, i2) => channel.Name || `Channel ${i2}`) : [Channels.Name || `Channel ${0}`];
296389
- return { ...loader2, channels: channels2 };
296390
- }
296391
- case "ome-zarr": {
296392
- const { coordinateTransformations: coordinateTransformationsFromOptions } = metadata2 || {};
296393
- const root2 = await zarrOpenRoot(url, null, { requestInit: requestInit2 });
296394
- const loader2 = await loadOmeZarr(root2);
296395
- const { metadata: loaderMetadata } = loader2;
296396
- const { omero, multiscales } = loaderMetadata;
296397
- if (!Array.isArray(multiscales) || multiscales.length === 0) {
296398
- log$c.error("Multiscales array must exist and have at least one element");
296399
- }
296400
- const { coordinateTransformations } = multiscales[0];
296401
- const axes = getNgffAxes(multiscales[0].axes);
296402
- const transformMatrixFromOptions = coordinateTransformationsToMatrix(coordinateTransformationsFromOptions, axes);
296403
- const transformMatrixFromFile = coordinateTransformationsToMatrix(coordinateTransformations, axes);
296404
- const transformMatrix = transformMatrixFromFile.multiplyLeft(transformMatrixFromOptions);
296405
- const { channels: channels2, name: omeroName } = omero;
296406
- return {
296407
- name: omeroName || "Image",
296408
- channels: channels2.map((c2, i2) => c2.label || `Channel ${i2}`),
296409
- ...transformMatrix ? {
296410
- metadata: {
296411
- transform: {
296412
- matrix: transformMatrix
296413
- }
296630
+ return {
296631
+ data: source2,
296632
+ metadata: { dimensions, transform: transform4 },
296633
+ channels: (dimensions.find((d) => d.field === "channel") || dimensions[0]).values
296634
+ };
296635
+ }
296636
+ case "ome-tiff": {
296637
+ let loader2;
296638
+ if (metadata2 == null ? void 0 : metadata2.omeTiffOffsetsUrl) {
296639
+ try {
296640
+ const res = await fetch(metadata2.omeTiffOffsetsUrl, requestInit2 || {});
296641
+ if (!res.ok)
296642
+ throw new Error(`Offsets not found: ${res.status} from ${res.url}`);
296643
+ const offsets2 = await res.json();
296644
+ loader2 = await loadOmeTiff(url, {
296645
+ offsets: offsets2,
296646
+ headers: requestInit2 == null ? void 0 : requestInit2.headers
296647
+ });
296648
+ } catch (err2) {
296649
+ log$c.error("Error loading OME-TIFF offsets:", err2);
296650
+ throw err2;
296414
296651
  }
296415
- } : {},
296416
- ...loader2
296417
- };
296418
- }
296419
- default: {
296420
- throw Error(`Image type (${type2}) is not supported`);
296652
+ } else {
296653
+ loader2 = await loadOmeTiff(url, { headers: requestInit2 == null ? void 0 : requestInit2.headers });
296654
+ }
296655
+ const { Pixels: { Channels } } = loader2.metadata;
296656
+ const channels2 = Array.isArray(Channels) ? Channels.map((channel, i2) => channel.Name || `Channel ${i2}`) : [Channels.Name || `Channel ${0}`];
296657
+ return { ...loader2, channels: channels2 };
296658
+ }
296659
+ case "ome-zarr": {
296660
+ const { coordinateTransformations: coordinateTransformationsFromOptions } = metadata2 || {};
296661
+ const root2 = await zarrOpenRoot(url, null, { requestInit: requestInit2 });
296662
+ const loader2 = await loadOmeZarr(root2);
296663
+ const { metadata: loaderMetadata } = loader2;
296664
+ const { omero, multiscales } = loaderMetadata;
296665
+ if (!Array.isArray(multiscales) || multiscales.length === 0) {
296666
+ throw new Error("Multiscales array must exist and have at least one element");
296667
+ }
296668
+ const { coordinateTransformations } = multiscales[0];
296669
+ const axes = getNgffAxes(multiscales[0].axes);
296670
+ const transformMatrixFromOptions = coordinateTransformationsToMatrix(coordinateTransformationsFromOptions, axes);
296671
+ const transformMatrixFromFile = coordinateTransformationsToMatrix(coordinateTransformations, axes);
296672
+ const transformMatrix = transformMatrixFromFile.multiplyLeft(transformMatrixFromOptions);
296673
+ const { channels: channels2, name: omeroName } = omero;
296674
+ return {
296675
+ name: omeroName || "Image",
296676
+ channels: channels2.map((c2, i2) => c2.label || `Channel ${i2}`),
296677
+ ...transformMatrix ? { metadata: { transform: { matrix: transformMatrix } } } : {},
296678
+ ...loader2
296679
+ };
296680
+ }
296681
+ default: {
296682
+ const errorMessage = `Image type (${type2}) is not supported`;
296683
+ log$c.error(errorMessage);
296684
+ throw new Error(errorMessage);
296685
+ }
296421
296686
  }
296687
+ } catch (error2) {
296688
+ log$c.error("Error in initLoader:", error2);
296689
+ throw error2;
296422
296690
  }
296423
296691
  }
296424
296692
  class RasterLoader extends JsonLoader {
@@ -296573,6 +296841,15 @@ function basename(path2) {
296573
296841
  }
296574
296842
  return result;
296575
296843
  }
296844
+ function prependSlash(path2) {
296845
+ if (typeof path2 === "string" && path2.length >= 1) {
296846
+ if (path2.charAt(0) === "/") {
296847
+ return path2;
296848
+ }
296849
+ return `/${path2}`;
296850
+ }
296851
+ return path2;
296852
+ }
296576
296853
  class AnnDataSource extends ZarrDataSource {
296577
296854
  /**
296578
296855
  *
@@ -296640,29 +296917,33 @@ class AnnDataSource extends ZarrDataSource {
296640
296917
  }
296641
296918
  /**
296642
296919
  *
296643
- * @param {string} path
296920
+ * @param {string} pathOrig
296644
296921
  * @returns
296645
296922
  */
296646
- async _loadColumn(path2) {
296923
+ async _loadColumn(pathOrig) {
296647
296924
  const { storeRoot } = this;
296648
- const prefix2 = dirname(path2);
296925
+ const path2 = prependSlash(pathOrig);
296926
+ const prefixOrig = dirname(path2);
296927
+ const prefix2 = prependSlash(prefixOrig);
296649
296928
  const { categories, "encoding-type": encodingType } = await this.getJson(`${path2}/.zattrs`);
296650
296929
  let categoriesValues;
296651
296930
  let codesPath;
296652
296931
  if (categories) {
296653
- const { dtype } = await open$1(storeRoot.resolve(`/${prefix2}/${categories}`), { kind: "array" });
296654
- if (dtype === "v2:object") {
296655
- categoriesValues = await this.getFlatArrDecompressed(`/${prefix2}/${categories}`);
296932
+ const { dtype } = await open$1(storeRoot.resolve(`${prefix2}/${categories}`), { kind: "array" });
296933
+ if (dtype === "v2:object" || dtype === "|O") {
296934
+ categoriesValues = await this.getFlatArrDecompressed(`${prefix2}/${categories}`);
296656
296935
  }
296657
296936
  } else if (encodingType === "categorical") {
296658
- const { dtype } = await open$1(storeRoot.resolve(`/${path2}/categories`), { kind: "array" });
296659
- if (dtype === "v2:object") {
296660
- categoriesValues = await this.getFlatArrDecompressed(`/${path2}/categories`);
296937
+ const { dtype } = await open$1(storeRoot.resolve(`${path2}/categories`), { kind: "array" });
296938
+ if (dtype === "v2:object" || dtype === "|O") {
296939
+ categoriesValues = await this.getFlatArrDecompressed(`${path2}/categories`);
296661
296940
  }
296662
- codesPath = `/${path2}/codes`;
296941
+ codesPath = `${path2}/codes`;
296942
+ } else if (encodingType === "string-array") {
296943
+ return this.getFlatArrDecompressed(path2);
296663
296944
  } else {
296664
- const { dtype } = await open$1(storeRoot.resolve(`/${path2}`), { kind: "array" });
296665
- if (dtype === "v2:object") {
296945
+ const { dtype } = await open$1(storeRoot.resolve(path2), { kind: "array" });
296946
+ if (dtype === "v2:object" || dtype === "|O") {
296666
296947
  return this.getFlatArrDecompressed(path2);
296667
296948
  }
296668
296949
  }
@@ -296736,7 +297017,7 @@ class AnnDataSource extends ZarrDataSource {
296736
297017
  if (this.obsIndex) {
296737
297018
  return this.obsIndex;
296738
297019
  }
296739
- this.obsIndex = this.getJson("obs/.zattrs").then(({ _index }) => this.getFlatArrDecompressed(`/obs/${_index}`));
297020
+ this.obsIndex = this.getJson("obs/.zattrs").then(({ _index }) => this._loadColumn(`/obs/${_index}`));
296740
297021
  return this.obsIndex;
296741
297022
  }
296742
297023
  /**
@@ -296747,7 +297028,7 @@ class AnnDataSource extends ZarrDataSource {
296747
297028
  */
296748
297029
  loadDataFrameIndex(path2 = void 0) {
296749
297030
  const dfPath = path2 ? dirname(path2) : "";
296750
- return this.getJson(`${dfPath}/.zattrs`).then(({ _index }) => this.getFlatArrDecompressed(`${dfPath.length > 0 ? "/" : ""}${dfPath}/${_index}`));
297031
+ return this.getJson(`${dfPath}/.zattrs`).then(({ _index }) => this._loadColumn(`${dfPath.length > 0 ? "/" : ""}${dfPath}/${_index}`));
296751
297032
  }
296752
297033
  /**
296753
297034
  * Class method for loading the var index.
@@ -296758,7 +297039,7 @@ class AnnDataSource extends ZarrDataSource {
296758
297039
  if (this.varIndex) {
296759
297040
  return this.varIndex;
296760
297041
  }
296761
- this.varIndex = this.getJson("var/.zattrs").then(({ _index }) => this.getFlatArrDecompressed(`/var/${_index}`));
297042
+ this.varIndex = this.getJson("var/.zattrs").then(({ _index }) => this._loadColumn(`/var/${_index}`));
296762
297043
  return this.varIndex;
296763
297044
  }
296764
297045
  /**
@@ -297549,6 +297830,11 @@ class ObsSegmentationsAnndataLoader extends AbstractTwoStepLoader {
297549
297830
  }
297550
297831
  }
297551
297832
  class ObsSetsAnndataLoader extends AbstractTwoStepLoader {
297833
+ constructor(dataSource, params2) {
297834
+ super(dataSource, params2);
297835
+ this.region = null;
297836
+ this.tablePath = null;
297837
+ }
297552
297838
  loadObsIndices() {
297553
297839
  var _a3;
297554
297840
  const { options } = this;
@@ -297583,7 +297869,7 @@ class ObsSetsAnndataLoader extends AbstractTwoStepLoader {
297583
297869
  if (!this.cachedResult) {
297584
297870
  const { options } = this;
297585
297871
  this.cachedResult = Promise.all([
297586
- this.dataSource.loadObsIndex(),
297872
+ this.dataSource.loadObsIndex(this.tablePath),
297587
297873
  this.loadObsIndices(),
297588
297874
  this.loadCellSetIds(),
297589
297875
  this.loadCellSetScores()
@@ -297911,11 +298197,11 @@ let FeatureStatsAnndataLoader$1 = class FeatureStatsAnndataLoader extends Abstra
297911
298197
  const rawSampleSetSelection = sampleSetSelection;
297912
298198
  if (sampleSetSelection) {
297913
298199
  if (sampleSetSelection.length !== 2) {
297914
- return Promise.reject(new Error("Expected exactly two sample sets for volcano plot."));
298200
+ return null;
297915
298201
  }
297916
298202
  }
297917
298203
  if (!obsSetSelection) {
297918
- return Promise.reject(new Error("Expected obsSetSelection to be present."));
298204
+ return null;
297919
298205
  }
297920
298206
  const metadata2 = await this.loadMetadata();
297921
298207
  const matchingComparisons = [];
@@ -297988,9 +298274,21 @@ class FeatureStatsAnndataLoader2 extends AbstractTwoStepLoader {
297988
298274
  this.loadFeatureSetTerms(dfPath),
297989
298275
  this.loadSignificances(dfPath)
297990
298276
  ]);
298277
+ const cleanName = (s2) => {
298278
+ if (s2.includes("R-HSA-")) {
298279
+ return s2.substring(0, s2.indexOf("R-HSA-") - 1);
298280
+ }
298281
+ return s2;
298282
+ };
298283
+ const cleanTerm = (s2) => {
298284
+ if (s2.includes("R-HSA-")) {
298285
+ return `REACTOME:${s2.substring(s2.indexOf("R-HSA-"))}`;
298286
+ }
298287
+ return s2;
298288
+ };
297991
298289
  return {
297992
- featureSetName,
297993
- featureSetTerm,
298290
+ featureSetName: featureSetName.map((s2) => cleanName(s2)),
298291
+ featureSetTerm: featureSetTerm.map((s2) => cleanTerm(s2)),
297994
298292
  featureSetSignificance
297995
298293
  };
297996
298294
  }
@@ -298019,30 +298317,31 @@ class FeatureStatsAnndataLoader2 extends AbstractTwoStepLoader {
298019
298317
  * @returns {Promise<LoaderResult<FeatureStatsData>>}
298020
298318
  */
298021
298319
  async loadMulti(volcanoOptions) {
298022
- const { analysisType: targetAnalysisType = "pertpy_hypergeometric" } = this.options;
298320
+ const { analysisType: targetAnalysisType = "pertpy_hypergeometric", featureSetLibrary: targetFeatureSetLibrary = "Reactome_2022" } = this.options;
298023
298321
  const { sampleSetSelection, obsSetSelection } = volcanoOptions || {};
298024
298322
  const rawObsSetSelection = obsSetSelection;
298025
298323
  const rawSampleSetSelection = sampleSetSelection;
298026
298324
  if (sampleSetSelection) {
298027
298325
  if (sampleSetSelection.length !== 2) {
298028
- return Promise.reject(new Error("Expected exactly two sample sets for volcano plot."));
298326
+ return null;
298029
298327
  }
298030
298328
  }
298031
298329
  if (!obsSetSelection) {
298032
- return Promise.reject(new Error("Expected obsSetSelection to be present."));
298330
+ return null;
298033
298331
  }
298034
298332
  const metadata2 = await this.loadMetadata();
298035
298333
  const matchingComparisons = [];
298036
298334
  Object.values(metadata2.comparisons).forEach((comparisonGroupObject) => {
298037
298335
  const { results } = comparisonGroupObject;
298038
298336
  results.forEach((resultObject) => {
298337
+ var _a3;
298039
298338
  const {
298040
298339
  analysis_type,
298041
- // analysis_params,
298340
+ analysis_params,
298042
298341
  coordination_values
298043
298342
  // path,
298044
298343
  } = resultObject;
298045
- if (analysis_type === targetAnalysisType) {
298344
+ if (analysis_type === targetAnalysisType && ((_a3 = analysis_params == null ? void 0 : analysis_params.pertpy_hypergeometric) == null ? void 0 : _a3.enrichr_library_name) === targetFeatureSetLibrary) {
298046
298345
  if (sampleSetSelection) {
298047
298346
  rawObsSetSelection.forEach((obsSetPath2) => {
298048
298347
  if (isEqual$5([obsSetPath2], coordination_values.obsSetFilter)) {
@@ -298115,10 +298414,6 @@ class ObsSetStatsAnndataLoader extends AbstractTwoStepLoader {
298115
298414
  }
298116
298415
  return values3.data;
298117
298416
  }
298118
- async loadCovariate(dfPath) {
298119
- const { covariateColumn } = this.options;
298120
- return this.dataSource._loadColumn(`${dfPath}/${covariateColumn}`);
298121
- }
298122
298417
  async loadObsSetNames(dfPath) {
298123
298418
  const { indexColumn } = this.options;
298124
298419
  if (indexColumn) {
@@ -298132,28 +298427,23 @@ class ObsSetStatsAnndataLoader extends AbstractTwoStepLoader {
298132
298427
  obsSetFoldChange,
298133
298428
  interceptExpectedSample,
298134
298429
  effectExpectedSample,
298135
- isCredibleEffect,
298430
+ isCredibleEffect
298136
298431
  // TODO: rather than passing this down,
298137
298432
  // do the fold change direction swapping in the loader
298138
298433
  // (as opposed to in the view).
298139
- // TODO: also, see https://github.com/keller-mark/compasce/issues/30
298140
- // which would allow not loading this column altogether.
298141
- covariate
298142
298434
  ] = await Promise.all([
298143
298435
  this.loadObsSetNames(dfPath),
298144
298436
  this.loadFoldChanges(dfPath),
298145
298437
  this.loadInterceptValues(dfPath),
298146
298438
  this.loadEffectValues(dfPath),
298147
- this.loadIsCredible(dfPath),
298148
- this.loadCovariate(dfPath)
298439
+ this.loadIsCredible(dfPath)
298149
298440
  ]);
298150
298441
  return {
298151
298442
  obsSetId,
298152
298443
  obsSetFoldChange,
298153
298444
  interceptExpectedSample,
298154
298445
  effectExpectedSample,
298155
- isCredibleEffect,
298156
- covariate
298446
+ isCredibleEffect
298157
298447
  };
298158
298448
  }
298159
298449
  /**
@@ -298186,10 +298476,10 @@ class ObsSetStatsAnndataLoader extends AbstractTwoStepLoader {
298186
298476
  const rawObsSetSelection = obsSetSelection;
298187
298477
  const rawSampleSetSelection = sampleSetSelection;
298188
298478
  if (!sampleSetSelection || (sampleSetSelection == null ? void 0 : sampleSetSelection.length) !== 2) {
298189
- return Promise.reject(new Error("Expected exactly two sample sets for cell type composition analysis plot."));
298479
+ return null;
298190
298480
  }
298191
298481
  if (!obsSetSelection) {
298192
- return Promise.reject(new Error("Expected obsSetSelection to be present."));
298482
+ return null;
298193
298483
  }
298194
298484
  const metadata2 = await this.loadMetadata();
298195
298485
  const rawObsSetGroups = Array.from(new Set(rawObsSetSelection.map((setPath) => setPath == null ? void 0 : setPath[0])));
@@ -298897,18 +299187,19 @@ class SpatialDataObsSetsLoader extends ObsSetsAnndataLoader {
298897
299187
  constructor(dataSource, params2) {
298898
299188
  super(dataSource, params2);
298899
299189
  this.region = this.options.region;
299190
+ this.tablePath = this.options.tablePath;
298900
299191
  }
298901
299192
  }
298902
- const pluralRegex = /^tables\/([^/]*)\/(.*)$/;
298903
- const singularRegex = /^table\/([^/]*)\/(.*)$/;
299193
+ const pluralRegex = /^tables\/([^/]*)(\/?)(.*)$/;
299194
+ const singularRegex = /^table\/([^/]*)(\/?)(.*)$/;
298904
299195
  function getTablePrefix(arrPath) {
298905
299196
  if (arrPath) {
298906
299197
  const pluralMatches = arrPath.match(pluralRegex);
298907
- if (pluralMatches && pluralMatches.length === 3) {
299198
+ if (pluralMatches && pluralMatches.length >= 3) {
298908
299199
  return `tables/${pluralMatches[1]}/`;
298909
299200
  }
298910
299201
  const singularMatches = arrPath.match(singularRegex);
298911
- if (singularMatches && singularMatches.length === 3) {
299202
+ if (singularMatches && singularMatches.length >= 3) {
298912
299203
  return `table/${singularMatches[1]}/`;
298913
299204
  }
298914
299205
  }
@@ -351498,7 +351789,7 @@ function loadPathwayNodes() {
351498
351789
  kgId: d.id,
351499
351790
  label: d.pathway,
351500
351791
  // For reactome
351501
- term: `reactome:${d.acc}`,
351792
+ term: `REACTOME:${d.acc}`,
351502
351793
  // For reactome
351503
351794
  // label: d.ontology_label, // For GO_BP
351504
351795
  // term: d.acc, // For GO_BP
@@ -351565,7 +351856,11 @@ async function loadPathwayToGeneEdges() {
351565
351856
  }));
351566
351857
  });
351567
351858
  }
351568
- async function transformFeature({ queryClient }, node2, targetModality) {
351859
+ async function transformFeature({ queryClient }, nodeOrig, targetModality) {
351860
+ var _a3;
351861
+ const node2 = {
351862
+ ...nodeOrig
351863
+ };
351569
351864
  if (targetModality === node2.nodeType) {
351570
351865
  return [node2];
351571
351866
  }
@@ -351581,6 +351876,19 @@ async function transformFeature({ queryClient }, node2, targetModality) {
351581
351876
  staleTime: Infinity,
351582
351877
  queryFn: loadPathwayToGeneEdges
351583
351878
  });
351879
+ if (!node2.kgId) {
351880
+ const pathwayNodes = await queryClient.fetchQuery({
351881
+ queryKey: ["pathwayNodes"],
351882
+ staleTime: Infinity,
351883
+ queryFn: loadPathwayNodes
351884
+ });
351885
+ const foundId = (_a3 = pathwayNodes.find((n3) => n3.term === node2.term)) == null ? void 0 : _a3.kgId;
351886
+ if (foundId) {
351887
+ node2.kgId = foundId;
351888
+ } else {
351889
+ console.warn("Could not find matching pathway node based on term.");
351890
+ }
351891
+ }
351584
351892
  const matchingEdges = pathwayGeneEdges.filter((d) => d.source === node2.kgId);
351585
351893
  const matchingGeneIds = matchingEdges.map((d) => d.target);
351586
351894
  const matchingGenes = geneNodes.filter((d) => matchingGeneIds.includes(d.kgId));
@@ -352469,6 +352777,17 @@ const baseCoordinationTypes = [
352469
352777
  null,
352470
352778
  z.array(z.string()).nullable()
352471
352779
  ),
352780
+ new PluginCoordinationType(CoordinationType$1.FEATURE_AGGREGATION_STRATEGY, null, z.union([
352781
+ z.enum([
352782
+ "first",
352783
+ "last",
352784
+ "mean",
352785
+ "sum",
352786
+ "difference"
352787
+ ]),
352788
+ // An index of a featureSelection array element.
352789
+ z.number()
352790
+ ]).nullable()),
352472
352791
  new PluginCoordinationType(
352473
352792
  CoordinationType$1.FEATURE_SET_SELECTION,
352474
352793
  null,