@vitessce/scatterplot 3.1.3 → 3.2.0

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.
@@ -2976,17 +2976,17 @@ let COLOR;
2976
2976
  COLOR2[COLOR2["BRIGHT_CYAN"] = 96] = "BRIGHT_CYAN";
2977
2977
  COLOR2[COLOR2["BRIGHT_WHITE"] = 97] = "BRIGHT_WHITE";
2978
2978
  })(COLOR || (COLOR = {}));
2979
- function getColor(color) {
2979
+ function getColor$1(color) {
2980
2980
  return typeof color === "string" ? COLOR[color.toUpperCase()] || COLOR.WHITE : color;
2981
2981
  }
2982
2982
  function addColor(string, color, background) {
2983
2983
  if (!isBrowser$3 && typeof string === "string") {
2984
2984
  if (color) {
2985
- color = getColor(color);
2985
+ color = getColor$1(color);
2986
2986
  string = "\x1B[".concat(color, "m").concat(string, "\x1B[39m");
2987
2987
  }
2988
2988
  if (background) {
2989
- color = getColor(background);
2989
+ color = getColor$1(background);
2990
2990
  string = "\x1B[".concat(background + 10, "m").concat(string, "\x1B[49m");
2991
2991
  }
2992
2992
  }
@@ -13010,7 +13010,7 @@ function negate(out, a2) {
13010
13010
  out[2] = -a2[2];
13011
13011
  return out;
13012
13012
  }
13013
- function normalize$3(out, a2) {
13013
+ function normalize$4(out, a2) {
13014
13014
  var x2 = a2[0];
13015
13015
  var y2 = a2[1];
13016
13016
  var z2 = a2[2];
@@ -14319,7 +14319,7 @@ function squaredLength$1(a2) {
14319
14319
  var w2 = a2[3];
14320
14320
  return x2 * x2 + y2 * y2 + z2 * z2 + w2 * w2;
14321
14321
  }
14322
- function normalize$2(out, a2) {
14322
+ function normalize$3(out, a2) {
14323
14323
  var x2 = a2[0];
14324
14324
  var y2 = a2[1];
14325
14325
  var z2 = a2[2];
@@ -14956,7 +14956,7 @@ var dot$1 = dot$2;
14956
14956
  var lerp$1 = lerp$2;
14957
14957
  var length$2 = length$3;
14958
14958
  var squaredLength = squaredLength$1;
14959
- var normalize$1 = normalize$2;
14959
+ var normalize$2 = normalize$3;
14960
14960
  var rotationTo = function() {
14961
14961
  var tmpvec3 = create$3();
14962
14962
  var xUnitVec3 = fromValues(1, 0, 0);
@@ -14967,7 +14967,7 @@ var rotationTo = function() {
14967
14967
  cross$1(tmpvec3, xUnitVec3, a2);
14968
14968
  if (len(tmpvec3) < 1e-6)
14969
14969
  cross$1(tmpvec3, yUnitVec3, a2);
14970
- normalize$3(tmpvec3, tmpvec3);
14970
+ normalize$4(tmpvec3, tmpvec3);
14971
14971
  setAxisAngle(out, tmpvec3, Math.PI);
14972
14972
  return out;
14973
14973
  } else if (dot2 > 0.999999) {
@@ -14982,7 +14982,7 @@ var rotationTo = function() {
14982
14982
  out[1] = tmpvec3[1];
14983
14983
  out[2] = tmpvec3[2];
14984
14984
  out[3] = 1 + dot2;
14985
- return normalize$1(out, out);
14985
+ return normalize$2(out, out);
14986
14986
  }
14987
14987
  };
14988
14988
  }();
@@ -15008,7 +15008,7 @@ var rotationTo = function() {
15008
15008
  matr[2] = -view[0];
15009
15009
  matr[5] = -view[1];
15010
15010
  matr[8] = -view[2];
15011
- return normalize$1(out, fromMat3(out, matr));
15011
+ return normalize$2(out, fromMat3(out, matr));
15012
15012
  };
15013
15013
  })();
15014
15014
  const IDENTITY_QUATERNION = [0, 0, 0, 1];
@@ -36697,7 +36697,7 @@ function copyFlatRing(target, targetStartIndex, positions, size, srcStartIndex =
36697
36697
  modifyPolygonWindingDirection(target, windingDirection, windingOptions);
36698
36698
  return targetIndex;
36699
36699
  }
36700
- function normalize(polygon2, positionSize) {
36700
+ function normalize$1(polygon2, positionSize) {
36701
36701
  validate(polygon2);
36702
36702
  const positions = [];
36703
36703
  const holeIndices = [];
@@ -36803,7 +36803,7 @@ class PolygonTesselator extends Tesselator {
36803
36803
  }
36804
36804
  normalizeGeometry(polygon2) {
36805
36805
  if (this.normalize) {
36806
- const normalizedPolygon = normalize(polygon2, this.positionSize);
36806
+ const normalizedPolygon = normalize$1(polygon2, this.positionSize);
36807
36807
  if (this.opts.resolution) {
36808
36808
  return cutPolygonByGrid(getPositions(normalizedPolygon), getHoleIndices(normalizedPolygon), {
36809
36809
  size: this.positionSize,
@@ -37425,7 +37425,7 @@ class PolygonLayer extends CompositeLayer {
37425
37425
  objectInfo.index++;
37426
37426
  let polygon2 = getPolygon(object2, objectInfo);
37427
37427
  if (_normalize) {
37428
- polygon2 = normalize(polygon2, positionSize);
37428
+ polygon2 = normalize$1(polygon2, positionSize);
37429
37429
  }
37430
37430
  const {
37431
37431
  holeIndices
@@ -82840,7 +82840,7 @@ function clipExtent(x02, y02, x12, y12) {
82840
82840
  return clipStream;
82841
82841
  };
82842
82842
  }
82843
- function extent() {
82843
+ function extent$1() {
82844
82844
  var x02 = 0, y02 = 0, x12 = 960, y12 = 500, cache2, cacheStream, clip2;
82845
82845
  return clip2 = {
82846
82846
  stream: function(stream) {
@@ -84247,7 +84247,7 @@ const d3Geo$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
84247
84247
  geoBounds: bounds,
84248
84248
  geoCentroid: centroid$3,
84249
84249
  geoCircle: circle$2,
84250
- geoClipExtent: extent,
84250
+ geoClipExtent: extent$1,
84251
84251
  geoConicConformal: conicConformal,
84252
84252
  geoConicConformalRaw: conicConformalRaw,
84253
84253
  geoConicEqualArea: conicEqualArea,
@@ -103488,28 +103488,38 @@ const PASS_THROUGH_PROPS = [
103488
103488
  ];
103489
103489
  class SelectionLayer extends CompositeLayer {
103490
103490
  _selectPolygonObjects(coordinates2) {
103491
- const { onSelect, getCellCoords, cellsQuadTree, flipY } = this.props;
103491
+ const { flipY, obsLayers } = this.props;
103492
103492
  const flippedCoordinates = flipY ? coordinates2.map((poly) => poly.map((p) => [p[0], -p[1]])) : coordinates2;
103493
103493
  const selectedPolygon = polygon(flippedCoordinates);
103494
- const pickingInfos = [];
103495
- cellsQuadTree.visit((node, x02, y02, x12, y12) => {
103496
- const nodePoints = [[[x02, y02], [x12, y02], [x12, y12], [x02, y12], [x02, y02]]];
103497
- const nodePolygon = polygon(nodePoints);
103498
- const nodePolygonContainsSelectedPolygon = booleanContains(nodePolygon, selectedPolygon);
103499
- const nodePolygonWithinSelectedPolygon = booleanWithin(nodePolygon, selectedPolygon);
103500
- const nodePolygonOverlapsSelectedPolgyon = booleanOverlap(nodePolygon, selectedPolygon);
103501
- if (!nodePolygonContainsSelectedPolygon && !nodePolygonWithinSelectedPolygon && !nodePolygonOverlapsSelectedPolgyon) {
103502
- return true;
103503
- }
103504
- if (node.data && booleanPointInPolygon$1(point([].slice.call(getCellCoords(node.data))), selectedPolygon)) {
103505
- pickingInfos.push(node.data);
103506
- }
103507
- return false;
103494
+ obsLayers.forEach((obsLayer) => {
103495
+ const { getObsCoords, obsQuadTree, obsIndex, onSelect: layerOnSelect } = obsLayer;
103496
+ const pickingInfos = [];
103497
+ obsQuadTree == null ? void 0 : obsQuadTree.visit((node, x02, y02, x12, y12) => {
103498
+ const nodePoints = [[[x02, y02], [x12, y02], [x12, y12], [x02, y12], [x02, y02]]];
103499
+ const nodePolygon = polygon(nodePoints);
103500
+ const nodePolygonContainsSelectedPolygon = booleanContains(nodePolygon, selectedPolygon);
103501
+ const nodePolygonWithinSelectedPolygon = booleanWithin(nodePolygon, selectedPolygon);
103502
+ const nodePolygonOverlapsSelectedPolgyon = booleanOverlap(nodePolygon, selectedPolygon);
103503
+ if (!nodePolygonContainsSelectedPolygon && !nodePolygonWithinSelectedPolygon && !nodePolygonOverlapsSelectedPolgyon) {
103504
+ return true;
103505
+ }
103506
+ if (node.data && booleanPointInPolygon$1(point([].slice.call(getObsCoords(node.data))), selectedPolygon)) {
103507
+ pickingInfos.push(node.data);
103508
+ }
103509
+ return false;
103510
+ });
103511
+ const pickingIds = pickingInfos.map((obsI) => obsIndex[obsI]);
103512
+ layerOnSelect(pickingIds);
103513
+ });
103514
+ }
103515
+ _selectEmpty() {
103516
+ const { obsLayers } = this.props;
103517
+ obsLayers.forEach((obsLayer) => {
103518
+ const { onSelect: layerOnSelect } = obsLayer;
103519
+ layerOnSelect([]);
103508
103520
  });
103509
- onSelect({ pickingInfos });
103510
103521
  }
103511
103522
  renderLayers() {
103512
- const { onSelect } = this.props;
103513
103523
  const mode = MODE_MAP[this.props.selectionType] || distEs6.ViewMode;
103514
103524
  const inheritedProps = {};
103515
103525
  PASS_THROUGH_PROPS.forEach((p) => {
@@ -103531,7 +103541,7 @@ class SelectionLayer extends CompositeLayer {
103531
103541
  const { coordinates: coordinates2 } = updatedData.features[0].geometry;
103532
103542
  this._selectPolygonObjects(coordinates2);
103533
103543
  } else if (editType === EDIT_TYPE_CLEAR) {
103534
- onSelect({ pickingInfos: [] });
103544
+ this._selectEmpty();
103535
103545
  }
103536
103546
  },
103537
103547
  _subLayerProps: {
@@ -103563,25 +103573,23 @@ SelectionLayer.defaultProps = defaultProps$f;
103563
103573
  function getBaseLayerId(layerId) {
103564
103574
  return `base-${layerId}`;
103565
103575
  }
103566
- function getSelectionLayers(tool, zoom, layerId, getCellCoords, obsIndex, updateCellsSelection, cellsQuadTree, flipY = false) {
103576
+ const onSelectNoop = ({ pickingInfos }) => {
103577
+ };
103578
+ function getSelectionLayer(tool, zoom, layerId, obsLayers, flipY = false) {
103567
103579
  if (!tool) {
103568
103580
  return [];
103569
103581
  }
103570
103582
  const cellBaseLayerId = getBaseLayerId(layerId);
103571
103583
  const editHandlePointRadius = 5 / (zoom + 16);
103572
- return [new SelectionLayer({
103584
+ return new SelectionLayer({
103573
103585
  id: "selection",
103574
103586
  flipY,
103575
- cellsQuadTree,
103576
- getCellCoords,
103587
+ obsLayers,
103577
103588
  coordinateSystem: COORDINATE_SYSTEM.CARTESIAN,
103578
103589
  selectionType: tool,
103579
- onSelect: ({ pickingInfos }) => {
103580
- const cellIds = pickingInfos.map((i2) => obsIndex[i2]);
103581
- if (updateCellsSelection) {
103582
- updateCellsSelection(cellIds);
103583
- }
103584
- },
103590
+ // This onSelect is no longer used since
103591
+ // the obsLayers each have their own onSelect.
103592
+ onSelect: onSelectNoop,
103585
103593
  layerIds: [cellBaseLayerId],
103586
103594
  getTentativeFillColor: () => [255, 255, 255, 95],
103587
103595
  getTentativeLineColor: () => [143, 143, 143, 255],
@@ -103593,7 +103601,7 @@ function getSelectionLayers(tool, zoom, layerId, getCellCoords, obsIndex, update
103593
103601
  editHandlePointRadiusScale: 1,
103594
103602
  editHandlePointRadiusMinPixels: editHandlePointRadius,
103595
103603
  editHandlePointRadiusMaxPixels: 2 * editHandlePointRadius
103596
- })];
103604
+ });
103597
103605
  }
103598
103606
  const TILE_SIZE = 4096;
103599
103607
  const DATA_TEXTURE_SIZE = 4096;
@@ -104707,16 +104715,16 @@ function addDecoder(cases, importFn) {
104707
104715
  }
104708
104716
  cases.forEach((c2) => registry$1.set(c2, importFn));
104709
104717
  }
104710
- addDecoder([void 0, 1], () => import("./raw-2ee0835f.js").then((m2) => m2.default));
104711
- addDecoder(5, () => import("./lzw-6ec4deb9.js").then((m2) => m2.default));
104718
+ addDecoder([void 0, 1], () => import("./raw-b9a1aa09.js").then((m2) => m2.default));
104719
+ addDecoder(5, () => import("./lzw-91120d0e.js").then((m2) => m2.default));
104712
104720
  addDecoder(6, () => {
104713
104721
  throw new Error("old style JPEG compression is not supported.");
104714
104722
  });
104715
- addDecoder(7, () => import("./jpeg-09198c7a.js").then((m2) => m2.default));
104716
- addDecoder([8, 32946], () => import("./deflate-ac65438c.js").then((m2) => m2.default));
104717
- addDecoder(32773, () => import("./packbits-26db2d36.js").then((m2) => m2.default));
104718
- addDecoder(34887, () => import("./lerc-a1ea16ed.js").then((m2) => m2.default));
104719
- addDecoder(50001, () => import("./webimage-2075fc27.js").then((m2) => m2.default));
104723
+ addDecoder(7, () => import("./jpeg-46e4967f.js").then((m2) => m2.default));
104724
+ addDecoder([8, 32946], () => import("./deflate-9071f9f0.js").then((m2) => m2.default));
104725
+ addDecoder(32773, () => import("./packbits-ad7c6a7a.js").then((m2) => m2.default));
104726
+ addDecoder(34887, () => import("./lerc-f7e82495.js").then((m2) => m2.default));
104727
+ addDecoder(50001, () => import("./webimage-0722f414.js").then((m2) => m2.default));
104720
104728
  function decodeRowAcc(row, stride) {
104721
104729
  let length2 = row.length - stride;
104722
104730
  let offset5 = 0;
@@ -111509,7 +111517,7 @@ const SIGNAL_ABORTED = "__vivSignalAborted";
111509
111517
  addDecoder(5, () => LZWDecoder);
111510
111518
  const MAX_COLOR_INTENSITY = 255;
111511
111519
  const DEFAULT_COLOR_OFF = [0, 0, 0];
111512
- const MAX_CHANNELS = 6;
111520
+ const MAX_CHANNELS$1 = 6;
111513
111521
  const DEFAULT_FONT_FAMILY = "-apple-system, 'Helvetica Neue', Arial, sans-serif";
111514
111522
  const DTYPE_VALUES = {
111515
111523
  Uint8: {
@@ -113025,7 +113033,7 @@ const AdditiveColormapExtension = class extends LayerExtension {
113025
113033
  };
113026
113034
  AdditiveColormapExtension.extensionName = "AdditiveColormapExtension";
113027
113035
  AdditiveColormapExtension.defaultProps = defaultProps$4$1;
113028
- const fs$1$1 = `uniform vec3 transparentColor;
113036
+ const fs$1$2 = `uniform vec3 transparentColor;
113029
113037
  uniform bool useTransparentColor;
113030
113038
  uniform float opacity;
113031
113039
 
@@ -113052,12 +113060,12 @@ rgba = apply_opacity(rgb);
113052
113060
  `;
113053
113061
  const colorPalette = {
113054
113062
  name: "color-palette-module",
113055
- fs: fs$1$1,
113063
+ fs: fs$1$2,
113056
113064
  inject: {
113057
113065
  "fs:DECKGL_MUTATE_COLOR": DECKGL_MUTATE_COLOR
113058
113066
  }
113059
113067
  };
113060
- function padWithDefault$2(arr, defaultValue2, padWidth) {
113068
+ function padWithDefault$3(arr, defaultValue2, padWidth) {
113061
113069
  for (let i2 = 0; i2 < padWidth; i2 += 1) {
113062
113070
  arr.push(defaultValue2);
113063
113071
  }
@@ -113083,8 +113091,8 @@ function padColors({ colors, channelsVisible }) {
113083
113091
  const newColors = colors.map(
113084
113092
  (color, i2) => channelsVisible[i2] ? color.map((c2) => c2 / MAX_COLOR_INTENSITY) : DEFAULT_COLOR_OFF
113085
113093
  );
113086
- const padSize = MAX_CHANNELS - newColors.length;
113087
- const paddedColors = padWithDefault$2(
113094
+ const padSize = MAX_CHANNELS$1 - newColors.length;
113095
+ const paddedColors = padWithDefault$3(
113088
113096
  newColors,
113089
113097
  DEFAULT_COLOR_OFF,
113090
113098
  padSize
@@ -113203,7 +113211,7 @@ const lens = {
113203
113211
  `
113204
113212
  }
113205
113213
  };
113206
- const defaultProps$2$1 = {
113214
+ const defaultProps$2$2 = {
113207
113215
  lensEnabled: { type: "boolean", value: false, compare: true },
113208
113216
  lensSelection: { type: "number", value: 0, compare: true },
113209
113217
  lensRadius: { type: "number", value: 100, compare: true },
@@ -113225,7 +113233,7 @@ const LensExtension = class extends LayerExtension {
113225
113233
  }
113226
113234
  const onMouseMove = () => {
113227
113235
  const { viewportId } = layer.props;
113228
- const { lensRadius = defaultProps$2$1.lensRadius.value } = this.props;
113236
+ const { lensRadius = defaultProps$2$2.lensRadius.value } = this.props;
113229
113237
  if (!viewportId) {
113230
113238
  layer.setState({ unprojectLensBounds: [0, 0, 0, 0] });
113231
113239
  return;
@@ -113272,10 +113280,10 @@ const LensExtension = class extends LayerExtension {
113272
113280
  const { unprojectLensBounds = [0, 0, 0, 0] } = this.state;
113273
113281
  const {
113274
113282
  bounds: bounds2,
113275
- lensEnabled = defaultProps$2$1.lensEnabled.value,
113276
- lensSelection = defaultProps$2$1.lensSelection.value,
113277
- lensBorderColor = defaultProps$2$1.lensBorderColor.value,
113278
- lensBorderRadius = defaultProps$2$1.lensBorderRadius.value,
113283
+ lensEnabled = defaultProps$2$2.lensEnabled.value,
113284
+ lensSelection = defaultProps$2$2.lensSelection.value,
113285
+ lensBorderColor = defaultProps$2$2.lensBorderColor.value,
113286
+ lensBorderRadius = defaultProps$2$2.lensBorderRadius.value,
113279
113287
  colors,
113280
113288
  channelsVisible
113281
113289
  } = this.props;
@@ -113316,7 +113324,7 @@ const LensExtension = class extends LayerExtension {
113316
113324
  }
113317
113325
  };
113318
113326
  LensExtension.extensionName = "LensExtension";
113319
- LensExtension.defaultProps = defaultProps$2$1;
113327
+ LensExtension.defaultProps = defaultProps$2$2;
113320
113328
  function colormapModuleFactory3D(name2, apply_cmap) {
113321
113329
  const fs2 = `${apply_cmap}
113322
113330
 
@@ -113556,7 +113564,7 @@ const channels = {
113556
113564
  function range$3(len2) {
113557
113565
  return [...Array(len2).keys()];
113558
113566
  }
113559
- function padWithDefault$1(arr, defaultValue2, padWidth) {
113567
+ function padWithDefault$2(arr, defaultValue2, padWidth) {
113560
113568
  for (let i2 = 0; i2 < padWidth; i2 += 1) {
113561
113569
  arr.push(defaultValue2);
113562
113570
  }
@@ -113580,13 +113588,13 @@ function padContrastLimits({
113580
113588
  const newContrastLimits = contrastLimits.map(
113581
113589
  (slider, i2) => channelsVisible[i2] ? slider : [maxSliderValue, maxSliderValue]
113582
113590
  );
113583
- const padSize = MAX_CHANNELS - newContrastLimits.length;
113591
+ const padSize = MAX_CHANNELS$1 - newContrastLimits.length;
113584
113592
  if (padSize < 0) {
113585
113593
  throw Error(
113586
113594
  `${newContrastLimits.lengths} channels passed in, but only 6 are allowed.`
113587
113595
  );
113588
113596
  }
113589
- const paddedContrastLimits = padWithDefault$1(
113597
+ const paddedContrastLimits = padWithDefault$2(
113590
113598
  newContrastLimits,
113591
113599
  [maxSliderValue, maxSliderValue],
113592
113600
  padSize
@@ -113616,7 +113624,7 @@ function makeBoundingBox(viewState) {
113616
113624
  viewport.unproject([0, viewport.height])
113617
113625
  ];
113618
113626
  }
113619
- const fs$1 = `#define SHADER_NAME xr-layer-fragment-shader
113627
+ const fs$1$1 = `#define SHADER_NAME xr-layer-fragment-shader
113620
113628
 
113621
113629
  precision highp float;
113622
113630
  precision highp int;
@@ -113657,7 +113665,7 @@ void main() {
113657
113665
  DECKGL_FILTER_COLOR(gl_FragColor, geometry);
113658
113666
  }
113659
113667
  `;
113660
- const vs$1 = `#define SHADER_NAME xr-layer-vertex-shader
113668
+ const vs$1$1 = `#define SHADER_NAME xr-layer-vertex-shader
113661
113669
 
113662
113670
  attribute vec2 texCoords;
113663
113671
  attribute vec3 positions;
@@ -113676,7 +113684,7 @@ void main(void) {
113676
113684
  DECKGL_FILTER_COLOR(color, geometry);
113677
113685
  }
113678
113686
  `;
113679
- const coreShaderModule = { fs: fs$1, vs: vs$1 };
113687
+ const coreShaderModule = { fs: fs$1$1, vs: vs$1$1 };
113680
113688
  function validateWebGL2Filter(gl, interpolation) {
113681
113689
  const canShowFloat = hasFeature(gl, FEATURES$1.TEXTURE_FLOAT);
113682
113690
  const canShowLinear = hasFeature(gl, FEATURES$1.TEXTURE_FILTER_LINEAR_FLOAT);
@@ -114410,7 +114418,7 @@ function getPosition$1(boundingBox, position, length2) {
114410
114418
  }
114411
114419
  }
114412
114420
  }
114413
- const defaultProps$2 = {
114421
+ const defaultProps$2$1 = {
114414
114422
  pickable: { type: "boolean", value: true, compare: true },
114415
114423
  viewState: {
114416
114424
  type: "object",
@@ -114503,7 +114511,7 @@ const ScaleBarLayer = class extends CompositeLayer {
114503
114511
  }
114504
114512
  };
114505
114513
  ScaleBarLayer.layerName = "ScaleBarLayer";
114506
- ScaleBarLayer.defaultProps = defaultProps$2;
114514
+ ScaleBarLayer.defaultProps = defaultProps$2$1;
114507
114515
  const vs$2 = `#version 300 es
114508
114516
  #define SHADER_NAME xr-layer-vertex-shader
114509
114517
 
@@ -114909,7 +114917,7 @@ const XR3DLayer = class extends Layer {
114909
114917
  });
114910
114918
  const invertedScaleMatrix = scaleMatrix.clone().invert();
114911
114919
  const invertedResolutionMatrix = resolutionMatrix.clone().invert();
114912
- const paddedClippingPlanes = padWithDefault$1(
114920
+ const paddedClippingPlanes = padWithDefault$2(
114913
114921
  clippingPlanes.map(
114914
114922
  (p) => p.clone().transform(invertedScaleMatrix).transform(invertedResolutionMatrix)
114915
114923
  ),
@@ -115221,7 +115229,7 @@ const VolumeLayer = class extends CompositeLayer {
115221
115229
  };
115222
115230
  VolumeLayer.layerName = "VolumeLayer";
115223
115231
  VolumeLayer.defaultProps = defaultProps$9;
115224
- const vs = `
115232
+ const vs$1 = `
115225
115233
  #define SHADER_NAME bitmask-layer-vertex-shader
115226
115234
 
115227
115235
  attribute vec2 texCoords;
@@ -115242,7 +115250,7 @@ void main(void) {
115242
115250
  DECKGL_FILTER_COLOR(color, geometry);
115243
115251
  }
115244
115252
  `;
115245
- const fs = `
115253
+ const fs$1 = `
115246
115254
  #define SHADER_NAME bitmask-layer-fragment-shader
115247
115255
  precision highp float;
115248
115256
 
@@ -115310,14 +115318,14 @@ void main() {
115310
115318
  DECKGL_FILTER_COLOR(gl_FragColor, geometry);
115311
115319
  }
115312
115320
  `;
115313
- function padWithDefault(arr, defaultValue2, padWidth) {
115321
+ function padWithDefault$1(arr, defaultValue2, padWidth) {
115314
115322
  const newArr = [...arr];
115315
115323
  for (let i2 = 0; i2 < padWidth; i2 += 1) {
115316
115324
  newArr.push(defaultValue2);
115317
115325
  }
115318
115326
  return newArr;
115319
115327
  }
115320
- const defaultProps$1 = {
115328
+ const defaultProps$2 = {
115321
115329
  hoveredCell: { type: "number", value: null, compare: true },
115322
115330
  // We do not want to deep-compare cellColorData,
115323
115331
  // as it is potentially a TypedArray with millions of elements.
@@ -115329,13 +115337,13 @@ const defaultProps$1 = {
115329
115337
  // Same as with cellColorData, we do not want to deep-compare expressionData.
115330
115338
  expressionData: { type: "object", value: null, compare: 0 }
115331
115339
  };
115332
- class BitmaskLayer extends XRLayer {
115340
+ let BitmaskLayer$1 = class BitmaskLayer extends XRLayer {
115333
115341
  // eslint-disable-next-line class-methods-use-this
115334
115342
  getShaders() {
115335
115343
  const { colormap } = this.props;
115336
115344
  return {
115337
- fs,
115338
- vs,
115345
+ fs: fs$1,
115346
+ vs: vs$1,
115339
115347
  modules: [project32, picking],
115340
115348
  defines: {
115341
115349
  [COLORMAP_SHADER_PLACEHOLDER]: GLSL_COLORMAPS.includes(colormap) ? colormap : GLSL_COLORMAP_DEFAULT
@@ -115395,7 +115403,7 @@ class BitmaskLayer extends XRLayer {
115395
115403
  expressionTex,
115396
115404
  colorTexHeight: colorTex.height,
115397
115405
  colorTexWidth: colorTex.width,
115398
- channelsVisible: padWithDefault(
115406
+ channelsVisible: padWithDefault$1(
115399
115407
  channelsVisible,
115400
115408
  false,
115401
115409
  // There are six texture entries on the shaders
@@ -115432,9 +115440,9 @@ class BitmaskLayer extends XRLayer {
115432
115440
  type: GL$1.FLOAT
115433
115441
  });
115434
115442
  }
115435
- }
115436
- BitmaskLayer.layerName = "BitmaskLayer";
115437
- BitmaskLayer.defaultProps = defaultProps$1;
115443
+ };
115444
+ BitmaskLayer$1.layerName = "BitmaskLayer";
115445
+ BitmaskLayer$1.defaultProps = defaultProps$2;
115438
115446
  var pluralize = { exports: {} };
115439
115447
  (function(module2, exports2) {
115440
115448
  (function(root2, pluralize2) {
@@ -123869,8 +123877,10 @@ const ViewType$1 = {
123869
123877
  STATUS: "status",
123870
123878
  SCATTERPLOT: "scatterplot",
123871
123879
  SPATIAL: "spatial",
123880
+ SPATIAL_BETA: "spatialBeta",
123872
123881
  HEATMAP: "heatmap",
123873
123882
  LAYER_CONTROLLER: "layerController",
123883
+ LAYER_CONTROLLER_BETA: "layerControllerBeta",
123874
123884
  GENOMIC_PROFILES: "genomicProfiles",
123875
123885
  GATING: "gating",
123876
123886
  FEATURE_LIST: "featureList",
@@ -123882,20 +123892,24 @@ const ViewType$1 = {
123882
123892
  const DataType$1 = {
123883
123893
  OBS_LABELS: "obsLabels",
123884
123894
  OBS_EMBEDDING: "obsEmbedding",
123885
- OBS_LOCATIONS: "obsLocations",
123886
123895
  OBS_FEATURE_MATRIX: "obsFeatureMatrix",
123887
123896
  OBS_SETS: "obsSets",
123888
123897
  FEATURE_LABELS: "featureLabels",
123889
123898
  IMAGE: "image",
123890
123899
  OBS_SEGMENTATIONS: "obsSegmentations",
123891
123900
  NEIGHBORHOODS: "neighborhoods",
123892
- GENOMIC_PROFILES: "genomic-profiles"
123901
+ GENOMIC_PROFILES: "genomic-profiles",
123902
+ OBS_SPOTS: "obsSpots",
123903
+ OBS_POINTS: "obsPoints",
123904
+ OBS_LOCATIONS: "obsLocations"
123893
123905
  };
123894
123906
  const FileType$1 = {
123895
123907
  // Joint file types
123896
123908
  ANNDATA_ZARR: "anndata.zarr",
123897
123909
  // Atomic file types
123898
123910
  OBS_EMBEDDING_CSV: "obsEmbedding.csv",
123911
+ OBS_SPOTS_CSV: "obsSpots.csv",
123912
+ OBS_POINTS_CSV: "obsPoints.csv",
123899
123913
  OBS_LOCATIONS_CSV: "obsLocations.csv",
123900
123914
  OBS_LABELS_CSV: "obsLabels.csv",
123901
123915
  FEATURE_LABELS_CSV: "featureLabels.csv",
@@ -123908,6 +123922,8 @@ const FileType$1 = {
123908
123922
  OBS_FEATURE_MATRIX_ANNDATA_ZARR: "obsFeatureMatrix.anndata.zarr",
123909
123923
  OBS_SETS_ANNDATA_ZARR: "obsSets.anndata.zarr",
123910
123924
  OBS_EMBEDDING_ANNDATA_ZARR: "obsEmbedding.anndata.zarr",
123925
+ OBS_SPOTS_ANNDATA_ZARR: "obsSpots.anndata.zarr",
123926
+ OBS_POINTS_ANNDATA_ZARR: "obsPoints.anndata.zarr",
123911
123927
  OBS_LOCATIONS_ANNDATA_ZARR: "obsLocations.anndata.zarr",
123912
123928
  OBS_SEGMENTATIONS_ANNDATA_ZARR: "obsSegmentations.anndata.zarr",
123913
123929
  OBS_LABELS_ANNDATA_ZARR: "obsLabels.anndata.zarr",
@@ -123916,6 +123932,8 @@ const FileType$1 = {
123916
123932
  OBS_FEATURE_MATRIX_MUDATA_ZARR: "obsFeatureMatrix.mudata.zarr",
123917
123933
  OBS_SETS_MUDATA_ZARR: "obsSets.mudata.zarr",
123918
123934
  OBS_EMBEDDING_MUDATA_ZARR: "obsEmbedding.mudata.zarr",
123935
+ OBS_SPOTS_MUDATA_ZARR: "obsSpots.mudata.zarr",
123936
+ OBS_POINTS_MUDATA_ZARR: "obsPoints.mudata.zarr",
123919
123937
  OBS_LOCATIONS_MUDATA_ZARR: "obsLocations.mudata.zarr",
123920
123938
  OBS_SEGMENTATIONS_MUDATA_ZARR: "obsSegmentations.mudata.zarr",
123921
123939
  OBS_LABELS_MUDATA_ZARR: "obsLabels.mudata.zarr",
@@ -123959,10 +123977,8 @@ const FileType$1 = {
123959
123977
  ANNDATA_EXPRESSION_MATRIX_ZARR: "anndata-expression-matrix.zarr"
123960
123978
  };
123961
123979
  const CoordinationType$1 = {
123962
- // Meta coordination scopes
123963
123980
  META_COORDINATION_SCOPES: "metaCoordinationScopes",
123964
123981
  META_COORDINATION_SCOPES_BY: "metaCoordinationScopesBy",
123965
- // Other coordination scopes
123966
123982
  DATASET: "dataset",
123967
123983
  // Entity types
123968
123984
  OBS_TYPE: "obsType",
@@ -123988,6 +124004,7 @@ const CoordinationType$1 = {
123988
124004
  SPATIAL_TARGET_X: "spatialTargetX",
123989
124005
  SPATIAL_TARGET_Y: "spatialTargetY",
123990
124006
  SPATIAL_TARGET_Z: "spatialTargetZ",
124007
+ SPATIAL_TARGET_T: "spatialTargetT",
123991
124008
  SPATIAL_ROTATION_X: "spatialRotationX",
123992
124009
  SPATIAL_ROTATION_Y: "spatialRotationY",
123993
124010
  SPATIAL_ROTATION_Z: "spatialRotationZ",
@@ -124025,7 +124042,46 @@ const CoordinationType$1 = {
124025
124042
  GATING_FEATURE_SELECTION_X: "gatingFeatureSelectionX",
124026
124043
  GATING_FEATURE_SELECTION_Y: "gatingFeatureSelectionY",
124027
124044
  FEATURE_VALUE_TRANSFORM_COEFFICIENT: "featureValueTransformCoefficient",
124028
- TOOLTIPS_VISIBLE: "tooltipsVisible"
124045
+ TOOLTIPS_VISIBLE: "tooltipsVisible",
124046
+ FILE_UID: "fileUid",
124047
+ IMAGE_LAYER: "imageLayer",
124048
+ IMAGE_CHANNEL: "imageChannel",
124049
+ SEGMENTATION_LAYER: "segmentationLayer",
124050
+ SEGMENTATION_CHANNEL: "segmentationChannel",
124051
+ SPATIAL_TARGET_C: "spatialTargetC",
124052
+ SPATIAL_LAYER_VISIBLE: "spatialLayerVisible",
124053
+ SPATIAL_LAYER_OPACITY: "spatialLayerOpacity",
124054
+ SPATIAL_LAYER_COLORMAP: "spatialLayerColormap",
124055
+ SPATIAL_LAYER_TRANSPARENT_COLOR: "spatialLayerTransparentColor",
124056
+ SPATIAL_LAYER_MODEL_MATRIX: "spatialLayerModelMatrix",
124057
+ SPATIAL_SEGMENTATION_FILLED: "spatialSegmentationFilled",
124058
+ SPATIAL_SEGMENTATION_STROKE_WIDTH: "spatialSegmentationStrokeWidth",
124059
+ SPATIAL_CHANNEL_COLOR: "spatialChannelColor",
124060
+ SPATIAL_CHANNEL_VISIBLE: "spatialChannelVisible",
124061
+ SPATIAL_CHANNEL_OPACITY: "spatialChannelOpacity",
124062
+ SPATIAL_CHANNEL_WINDOW: "spatialChannelWindow",
124063
+ PHOTOMETRIC_INTERPRETATION: "photometricInterpretation",
124064
+ // For 3D volume rendering
124065
+ SPATIAL_RENDERING_MODE: "spatialRenderingMode",
124066
+ VOLUMETRIC_RENDERING_ALGORITHM: "volumetricRenderingAlgorithm",
124067
+ SPATIAL_TARGET_RESOLUTION: "spatialTargetResolution",
124068
+ // For clipping plane sliders
124069
+ SPATIAL_SLICE_X: "spatialSliceX",
124070
+ SPATIAL_SLICE_Y: "spatialSliceY",
124071
+ SPATIAL_SLICE_Z: "spatialSliceZ",
124072
+ // For spatial spot and point layers
124073
+ SPOT_LAYER: "spotLayer",
124074
+ POINT_LAYER: "pointLayer",
124075
+ SPATIAL_SPOT_RADIUS: "spatialSpotRadius",
124076
+ SPATIAL_SPOT_FILLED: "spatialSpotFilled",
124077
+ SPATIAL_SPOT_STROKE_WIDTH: "spatialSpotStrokeWidth",
124078
+ SPATIAL_LAYER_COLOR: "spatialLayerColor",
124079
+ PIXEL_HIGHLIGHT: "pixelHighlight",
124080
+ TOOLTIP_CROSSHAIRS_VISIBLE: "tooltipCrosshairsVisible",
124081
+ LEGEND_VISIBLE: "legendVisible",
124082
+ SPATIAL_CHANNEL_LABELS_VISIBLE: "spatialChannelLabelsVisible",
124083
+ SPATIAL_CHANNEL_LABELS_ORIENTATION: "spatialChannelLabelsOrientation",
124084
+ SPATIAL_CHANNEL_LABEL_SIZE: "spatialChannelLabelSize"
124029
124085
  };
124030
124086
  const ViewType = {
124031
124087
  GENES: [
@@ -124286,6 +124342,8 @@ const annDataObsSets = z.array(z.object({
124286
124342
  ]),
124287
124343
  scorePath: z.string().optional().describe("The location in the AnnData store for the set confidence scores, like 'obs/celltype_prediction_score.'")
124288
124344
  }));
124345
+ const annDataObsSpots = annDataObsm;
124346
+ const annDataObsPoints = annDataObsm;
124289
124347
  const annDataObsLocations = annDataObsm;
124290
124348
  const annDataObsEmbedding = annDataObsm;
124291
124349
  const annDataObsSegmentations = annDataObs;
@@ -124312,10 +124370,21 @@ z.object({
124312
124370
  z.object({
124313
124371
  obsIndex: z.string(),
124314
124372
  obsEmbedding: z.array(z.string()).length(2)
124373
+ // TODO: support 3D?
124374
+ });
124375
+ z.object({
124376
+ obsIndex: z.string(),
124377
+ obsSpots: z.array(z.string()).length(2)
124378
+ // TODO: support 3D?
124379
+ });
124380
+ z.object({
124381
+ obsIndex: z.string(),
124382
+ obsPoints: z.array(z.string()).length(3)
124315
124383
  });
124316
124384
  z.object({
124317
124385
  obsIndex: z.string(),
124318
124386
  obsLocations: z.array(z.string()).length(2)
124387
+ // TODO: support 3D?
124319
124388
  });
124320
124389
  z.object({
124321
124390
  obsIndex: z.string(),
@@ -124347,6 +124416,8 @@ z.object({
124347
124416
  ]),
124348
124417
  obsFeatureMatrix: annDataObsFeatureMatrix,
124349
124418
  obsSets: annDataObsSets,
124419
+ obsSpots: annDataObsSpots,
124420
+ obsPoints: annDataObsPoints,
124350
124421
  obsLocations: annDataObsLocations,
124351
124422
  obsSegmentations: annDataObsSegmentations,
124352
124423
  obsEmbedding: z.union([
@@ -130893,6 +130964,596 @@ function interpolateSequentialMulti(range2) {
130893
130964
  }
130894
130965
  interpolateRgbBasis(schemeRdBu);
130895
130966
  interpolateSequentialMulti(schemePlasma);
130967
+ const vs = `
130968
+ #define SHADER_NAME bitmask-layer-vertex-shader
130969
+
130970
+ attribute vec2 texCoords;
130971
+ attribute vec3 positions;
130972
+ attribute vec3 positions64Low;
130973
+ attribute vec3 instancePickingColors;
130974
+
130975
+ varying vec2 vTexCoord;
130976
+
130977
+ void main(void) {
130978
+ geometry.worldPosition = positions;
130979
+ geometry.uv = texCoords;
130980
+ geometry.pickingColor = instancePickingColors;
130981
+ gl_Position = project_position_to_clipspace(positions, positions64Low, vec3(0.0), geometry.position);
130982
+ DECKGL_FILTER_GL_POSITION(gl_Position, geometry);
130983
+ vTexCoord = texCoords;
130984
+ vec4 color = vec4(0.0);
130985
+ DECKGL_FILTER_COLOR(color, geometry);
130986
+ }
130987
+ `;
130988
+ const fs = `
130989
+ #define SHADER_NAME bitmask-layer-fragment-shader
130990
+ precision highp float;
130991
+
130992
+ ${colormaps}
130993
+
130994
+ // Note: can have a maximum of 16 textures in most browsers
130995
+ // Reference: https://webglreport.com/
130996
+
130997
+ // Data (mask) texture
130998
+ uniform sampler2D channel0;
130999
+ uniform sampler2D channel1;
131000
+ uniform sampler2D channel2;
131001
+ uniform sampler2D channel3;
131002
+ uniform sampler2D channel4;
131003
+ uniform sampler2D channel5;
131004
+ uniform sampler2D channel6;
131005
+
131006
+ // Color texture
131007
+ uniform float hovered;
131008
+
131009
+ // Channel-specific properties
131010
+ uniform bool channelsVisible[7];
131011
+ uniform float channelOpacities[7];
131012
+ uniform bool channelIsStaticColorMode[7]; // TODO: should this be a single float?
131013
+ uniform bool channelIsSetColorMode[7]; // TODO: should this be a single float?
131014
+
131015
+ // TODO: can array of tuples/vec2 be used?
131016
+ uniform float channelColormapRangeStarts[7];
131017
+ uniform float channelColormapRangeEnds[7];
131018
+
131019
+ uniform float multiFeatureTexSize;
131020
+
131021
+ // Use one expressionTex for all channels, using an offset mechanism.
131022
+ uniform sampler2D valueTex;
131023
+ uniform float valueTexOffsets[7];
131024
+ uniform float valueTexHeight;
131025
+
131026
+ // Textures for set colors, using the same offset mechanism.
131027
+ uniform sampler2D colorTex;
131028
+ uniform float colorTexOffsets[7];
131029
+ uniform float colorTexHeight;
131030
+
131031
+
131032
+ // Static colors
131033
+ // TODO: For some reason I cannot use uniform vec3 colors[7]; and i cannot figure out why.
131034
+ uniform vec3 color0;
131035
+ uniform vec3 color1;
131036
+ uniform vec3 color2;
131037
+ uniform vec3 color3;
131038
+ uniform vec3 color4;
131039
+ uniform vec3 color5;
131040
+ uniform vec3 color6;
131041
+
131042
+ // Info for edge-only mode
131043
+ uniform float scaleFactor;
131044
+ uniform bool channelsFilled[7];
131045
+ uniform float channelStrokeWidths[7];
131046
+
131047
+ // opacity
131048
+ uniform float opacity;
131049
+
131050
+ varying vec2 vTexCoord;
131051
+
131052
+ vec3 sampleAndGetData(sampler2D dataTex, vec2 coord, bool isFilled, float strokeWidth, bool isOn) {
131053
+ float sampledData = texture(dataTex, coord).r;
131054
+ float clampedSampledData = max(0., min(sampledData, 1.));
131055
+
131056
+ bool isEdge = true;
131057
+
131058
+ if(!isFilled) {
131059
+ vec2 uTextureSize = vec2(2048.0, 2048.0);
131060
+ vec2 onePixel = vec2(1.0, 1.0) / uTextureSize;
131061
+
131062
+ // Vary the edgeSize based on user-defined stroke width.
131063
+ float edgeSize = 150.0 * strokeWidth * scaleFactor;
131064
+
131065
+ float pixN = texture(dataTex, coord + vec2(0.0, onePixel.y * edgeSize)).r;
131066
+ float pixS = texture(dataTex, coord - vec2(0.0, onePixel.y * edgeSize)).r;
131067
+ float pixW = texture(dataTex, coord + vec2(onePixel.x * edgeSize, 0.0)).r;
131068
+ float pixE = texture(dataTex, coord - vec2(onePixel.x * edgeSize, 0.0)).r;
131069
+
131070
+ float pixNW = texture(dataTex, coord + vec2(onePixel.y * edgeSize, onePixel.y * edgeSize)).r;
131071
+ float pixNE = texture(dataTex, coord + vec2(-1.0 * onePixel.x * edgeSize, onePixel.y * edgeSize)).r;
131072
+ float pixSW = texture(dataTex, coord - vec2(onePixel.x * edgeSize, onePixel.y * edgeSize)).r;
131073
+ float pixSE = texture(dataTex, coord - vec2(-1.0 * onePixel.x * edgeSize, onePixel.y * edgeSize)).r;
131074
+
131075
+ isEdge = (pixN != sampledData || pixS != sampledData || pixW != sampledData || pixE != sampledData || pixNW != sampledData || pixNE != sampledData || pixSW != sampledData || pixSE != sampledData);
131076
+ }
131077
+ // Return a tuple of (sampledData, isEdge)
131078
+ return vec3(clampedSampledData * float(isOn), sampledData, float(isEdge));
131079
+ }
131080
+
131081
+ vec4 dataToColor(vec3 sampledDataAndIsEdge, bool isStaticColorMode, vec3 channelColor, float channelOpacity, float valueOffset, float rangeStart, float rangeEnd, bool isSetColorMode, float setColorOffset) {
131082
+ float clampedSampledDataAndIsOn = sampledDataAndIsEdge.x;
131083
+ float sampledData = sampledDataAndIsEdge.y;
131084
+ float isEdge = sampledDataAndIsEdge.z;
131085
+
131086
+
131087
+ vec4 hoveredColor = float(sampledData == hovered && sampledData > 0. && hovered > 0.) * vec4(0., 0., 1., 1.);
131088
+
131089
+ // Colors are laid out corresponding to ids in row-major order in the texture. So if width of the texture is 10, and you want ID 25,
131090
+ // you need coordinate (1, 4) (i.e 2 rows down, and 5 columns over indexed from 0 for a total of 25 units covered in row major order).
131091
+ float offsetSampledData = sampledData + valueOffset - 1.0;
131092
+ vec2 colorTexCoord = vec2(mod(offsetSampledData, multiFeatureTexSize) / multiFeatureTexSize, floor(offsetSampledData / multiFeatureTexSize) / (valueTexHeight - 1.));
131093
+
131094
+ // Get expression value
131095
+ float expressionValue = texture(valueTex, colorTexCoord).r / 255.;
131096
+ float scaledExpressionValue = (expressionValue - rangeStart) / max(0.005, (rangeEnd - rangeStart));
131097
+
131098
+
131099
+ // Get set color index value
131100
+ vec2 setIndicesTexCoord = vec2(mod(offsetSampledData, multiFeatureTexSize) / multiFeatureTexSize, floor(offsetSampledData / multiFeatureTexSize) / (valueTexHeight - 1.));
131101
+ float setColorIndex = texture(valueTex, setIndicesTexCoord).r;
131102
+
131103
+ // Initialize to the default "null" color.
131104
+ vec3 setColor = vec3(200. / 255., 200. / 255., 200. / 255.);
131105
+ if(setColorIndex != 0.) {
131106
+ // Subtract one from setColorIndex because we have already checked for the "null" value.
131107
+ setColorIndex = setColorIndex - 1.;
131108
+
131109
+ float setColorOffsetR = (setColorIndex + setColorOffset) * 3.0 + 0.0;
131110
+ vec2 setColorTexCoordR = vec2(mod(setColorOffsetR, multiFeatureTexSize) / multiFeatureTexSize, floor(setColorOffsetR / multiFeatureTexSize) / (colorTexHeight - 1.));
131111
+ float setColorR = texture(colorTex, setColorTexCoordR).r / 255.;
131112
+
131113
+ float setColorOffsetG = (setColorIndex + setColorOffset) * 3.0 + 1.0;
131114
+ vec2 setColorTexCoordG = vec2(mod(setColorOffsetG, multiFeatureTexSize) / multiFeatureTexSize, floor(setColorOffsetG / multiFeatureTexSize) / (colorTexHeight - 1.));
131115
+ float setColorG = texture(colorTex, setColorTexCoordG).r / 255.;
131116
+
131117
+ float setColorOffsetB = (setColorIndex + setColorOffset) * 3.0 + 2.0;
131118
+ vec2 setColorTexCoordB = vec2(mod(setColorOffsetB, multiFeatureTexSize) / multiFeatureTexSize, floor(setColorOffsetB / multiFeatureTexSize) / (colorTexHeight - 1.));
131119
+ float setColorB = texture(colorTex, setColorTexCoordB).r / 255.;
131120
+
131121
+ setColor = vec3(setColorR, setColorG, setColorB);
131122
+ }
131123
+
131124
+
131125
+ vec4 sampledColor = (1. - (float(isStaticColorMode) + float(isSetColorMode))) * vec4(COLORMAP_FUNC(clamp(scaledExpressionValue, 0.0, 1.0)).rgb, channelOpacity) + float(isStaticColorMode) * vec4(channelColor.rgb, channelOpacity) + float(isSetColorMode) * vec4(setColor, channelOpacity);
131126
+ // Only return a color if the data is non-zero.
131127
+
131128
+ return clampedSampledDataAndIsOn * isEdge * sampledColor;
131129
+ }
131130
+
131131
+ void main() {
131132
+
131133
+ // Get the color and alpha value for each channel.
131134
+ vec3 dat0 = sampleAndGetData(channel0, vTexCoord, channelsFilled[0], channelStrokeWidths[0], channelsVisible[0]);
131135
+ vec3 dat1 = sampleAndGetData(channel1, vTexCoord, channelsFilled[1], channelStrokeWidths[1], channelsVisible[1]);
131136
+ vec3 dat2 = sampleAndGetData(channel2, vTexCoord, channelsFilled[2], channelStrokeWidths[2], channelsVisible[2]);
131137
+ vec3 dat3 = sampleAndGetData(channel3, vTexCoord, channelsFilled[3], channelStrokeWidths[3], channelsVisible[3]);
131138
+ vec3 dat4 = sampleAndGetData(channel4, vTexCoord, channelsFilled[4], channelStrokeWidths[4], channelsVisible[4]);
131139
+ vec3 dat5 = sampleAndGetData(channel5, vTexCoord, channelsFilled[5], channelStrokeWidths[5], channelsVisible[5]);
131140
+ vec3 dat6 = sampleAndGetData(channel6, vTexCoord, channelsFilled[6], channelStrokeWidths[6], channelsVisible[6]);
131141
+
131142
+ vec4 val0 = dataToColor(dat0, channelIsStaticColorMode[0], color0, channelOpacities[0], valueTexOffsets[0], channelColormapRangeStarts[0], channelColormapRangeEnds[0], channelIsSetColorMode[0], colorTexOffsets[0]);
131143
+ vec4 val1 = dataToColor(dat1, channelIsStaticColorMode[1], color1, channelOpacities[1], valueTexOffsets[1], channelColormapRangeStarts[1], channelColormapRangeEnds[1], channelIsSetColorMode[1], colorTexOffsets[1]);
131144
+ vec4 val2 = dataToColor(dat2, channelIsStaticColorMode[2], color2, channelOpacities[2], valueTexOffsets[2], channelColormapRangeStarts[2], channelColormapRangeEnds[2], channelIsSetColorMode[2], colorTexOffsets[2]);
131145
+ vec4 val3 = dataToColor(dat3, channelIsStaticColorMode[3], color3, channelOpacities[3], valueTexOffsets[3], channelColormapRangeStarts[3], channelColormapRangeEnds[3], channelIsSetColorMode[3], colorTexOffsets[3]);
131146
+ vec4 val4 = dataToColor(dat4, channelIsStaticColorMode[4], color4, channelOpacities[4], valueTexOffsets[4], channelColormapRangeStarts[4], channelColormapRangeEnds[4], channelIsSetColorMode[4], colorTexOffsets[4]);
131147
+ vec4 val5 = dataToColor(dat5, channelIsStaticColorMode[5], color5, channelOpacities[5], valueTexOffsets[5], channelColormapRangeStarts[5], channelColormapRangeEnds[5], channelIsSetColorMode[5], colorTexOffsets[5]);
131148
+ vec4 val6 = dataToColor(dat6, channelIsStaticColorMode[6], color6, channelOpacities[6], valueTexOffsets[6], channelColormapRangeStarts[6], channelColormapRangeEnds[6], channelIsSetColorMode[6], colorTexOffsets[6]);
131149
+
131150
+ // If all of the channels are "empty", then discard this pixel so that it is not considered during picking.
131151
+ float emptyDat = 0.;
131152
+ if(dat0.x == emptyDat && dat1.x == emptyDat && dat2.x == emptyDat && dat3.x == emptyDat && dat4.x == emptyDat && dat5.x == emptyDat && dat6.x == emptyDat) {
131153
+ discard;
131154
+ }
131155
+
131156
+ // If the next channel color and the currently stored color (gl_FragColor) are identical,
131157
+ // or the next channel color is transparent black,
131158
+ // just use the currently stored color. Repeat this for all channels.
131159
+
131160
+ // Mix colors where necessary, using the alpha value of the next channel as the weight.
131161
+ // Use the maximum alpha value as the resulting alpha value.
131162
+ gl_FragColor = val0;
131163
+ gl_FragColor = (val1 == gl_FragColor || val1 == vec4(0.)) ? gl_FragColor : vec4(mix(gl_FragColor, val1, val1.a).rgb, max(gl_FragColor.a, val1.a));
131164
+ gl_FragColor = (val2 == gl_FragColor || val2 == vec4(0.)) ? gl_FragColor : vec4(mix(gl_FragColor, val2, val2.a).rgb, max(gl_FragColor.a, val2.a));
131165
+ gl_FragColor = (val3 == gl_FragColor || val3 == vec4(0.)) ? gl_FragColor : vec4(mix(gl_FragColor, val3, val3.a).rgb, max(gl_FragColor.a, val3.a));
131166
+ gl_FragColor = (val4 == gl_FragColor || val4 == vec4(0.)) ? gl_FragColor : vec4(mix(gl_FragColor, val4, val4.a).rgb, max(gl_FragColor.a, val4.a));
131167
+ gl_FragColor = (val5 == gl_FragColor || val5 == vec4(0.)) ? gl_FragColor : vec4(mix(gl_FragColor, val5, val5.a).rgb, max(gl_FragColor.a, val5.a));
131168
+ gl_FragColor = (val6 == gl_FragColor || val6 == vec4(0.)) ? gl_FragColor : vec4(mix(gl_FragColor, val6, val6.a).rgb, max(gl_FragColor.a, val6.a));
131169
+
131170
+
131171
+
131172
+ // TODO: multiply the resulting channel-level opacity value by the layer-level opacity value.
131173
+
131174
+ geometry.uv = vTexCoord;
131175
+ DECKGL_FILTER_COLOR(gl_FragColor, geometry);
131176
+ }
131177
+ `;
131178
+ function extent(values2, valueof) {
131179
+ let min;
131180
+ let max;
131181
+ if (valueof === void 0) {
131182
+ for (const value of values2) {
131183
+ if (value != null) {
131184
+ if (min === void 0) {
131185
+ if (value >= value)
131186
+ min = max = value;
131187
+ } else {
131188
+ if (min > value)
131189
+ min = value;
131190
+ if (max < value)
131191
+ max = value;
131192
+ }
131193
+ }
131194
+ }
131195
+ } else {
131196
+ let index2 = -1;
131197
+ for (let value of values2) {
131198
+ if ((value = valueof(value, ++index2, values2)) != null) {
131199
+ if (min === void 0) {
131200
+ if (value >= value)
131201
+ min = max = value;
131202
+ } else {
131203
+ if (min > value)
131204
+ min = value;
131205
+ if (max < value)
131206
+ max = value;
131207
+ }
131208
+ }
131209
+ }
131210
+ }
131211
+ return [min, max];
131212
+ }
131213
+ function normalize(arr) {
131214
+ const [min, max] = extent(arr);
131215
+ const ratio = 255 / (max - min);
131216
+ const data = new Uint8Array(arr.map((i2) => Math.floor((i2 - min) * ratio)));
131217
+ return data;
131218
+ }
131219
+ function multiSetsToTextureData(multiFeatureValues, setColorValues, channelIsSetColorMode, texSize) {
131220
+ let totalValuesLength = 0;
131221
+ let totalColorsLength = 0;
131222
+ channelIsSetColorMode.forEach((isSetColorMode, channelIndex) => {
131223
+ var _a2, _b, _c, _d, _e;
131224
+ if (isSetColorMode) {
131225
+ totalValuesLength += ((_b = (_a2 = setColorValues[channelIndex]) == null ? void 0 : _a2.obsIndex) == null ? void 0 : _b.length) || 0;
131226
+ totalColorsLength += (((_d = (_c = setColorValues[channelIndex]) == null ? void 0 : _c.setColors) == null ? void 0 : _d.length) || 0) * 3;
131227
+ } else {
131228
+ totalValuesLength += ((_e = multiFeatureValues[channelIndex]) == null ? void 0 : _e.length) || 0;
131229
+ }
131230
+ });
131231
+ const valueTexHeight = Math.max(2, Math.ceil(totalValuesLength / texSize));
131232
+ const colorTexHeight = Math.max(2, Math.ceil(totalColorsLength / texSize));
131233
+ if (valueTexHeight > texSize) {
131234
+ console.error("Error: length of concatenated quantitative feature values larger than maximum texture size");
131235
+ }
131236
+ if (colorTexHeight > texSize) {
131237
+ console.error("Error: length of concatenated quantitative feature values larger than maximum texture size");
131238
+ }
131239
+ const totalData = new Uint8Array(texSize * valueTexHeight);
131240
+ const totalColors = new Uint8Array(texSize * colorTexHeight);
131241
+ const indicesOffsets = [];
131242
+ const colorsOffsets = [];
131243
+ let indexOffset = 0;
131244
+ let colorOffset = 0;
131245
+ channelIsSetColorMode.forEach((isSetColorMode, channelIndex) => {
131246
+ if (isSetColorMode) {
131247
+ const { setColorIndices, setColors, obsIndex } = setColorValues[channelIndex] || {};
131248
+ if (setColorIndices && setColors && obsIndex) {
131249
+ for (let i2 = 0; i2 < obsIndex.length; i2++) {
131250
+ const colorIndex = setColorIndices.get(String(i2 + 1));
131251
+ totalData[indexOffset + i2] = colorIndex === void 0 ? 0 : colorIndex + 1;
131252
+ }
131253
+ for (let i2 = 0; i2 < setColors.length; i2++) {
131254
+ const { color: [r2, g2, b] } = setColors[i2];
131255
+ totalColors[(colorOffset + i2) * 3 + 0] = r2;
131256
+ totalColors[(colorOffset + i2) * 3 + 1] = g2;
131257
+ totalColors[(colorOffset + i2) * 3 + 2] = b;
131258
+ }
131259
+ }
131260
+ indicesOffsets.push(indexOffset);
131261
+ colorsOffsets.push(colorOffset);
131262
+ indexOffset += (obsIndex == null ? void 0 : obsIndex.length) || 0;
131263
+ colorOffset += (setColors == null ? void 0 : setColors.length) || 0;
131264
+ } else {
131265
+ const featureArr = multiFeatureValues[channelIndex];
131266
+ totalData.set(normalize(featureArr), indexOffset);
131267
+ indicesOffsets.push(indexOffset);
131268
+ indexOffset += featureArr.length;
131269
+ colorsOffsets.push(colorOffset);
131270
+ }
131271
+ });
131272
+ return [
131273
+ totalData,
131274
+ valueTexHeight,
131275
+ indicesOffsets,
131276
+ totalColors,
131277
+ colorTexHeight,
131278
+ colorsOffsets
131279
+ ];
131280
+ }
131281
+ const MAX_CHANNELS = 7;
131282
+ const MULTI_FEATURE_TEX_SIZE = 2048;
131283
+ function padWithDefault(arr, defaultValue2, padWidth) {
131284
+ const newArr = [...arr];
131285
+ for (let i2 = 0; i2 < padWidth; i2 += 1) {
131286
+ newArr.push(defaultValue2);
131287
+ }
131288
+ return newArr;
131289
+ }
131290
+ function getColor(arr) {
131291
+ return arr ? arr.map((v) => v / 255) : [0, 0, 0];
131292
+ }
131293
+ const defaultProps$1 = {
131294
+ channelStrokeWidths: { type: "array", value: null, compare: true },
131295
+ channelsFilled: { type: "array", value: null, compare: true },
131296
+ channelOpacities: { type: "array", value: null, compare: true },
131297
+ channelColors: { type: "array", value: null, compare: true },
131298
+ hoveredCell: { type: "number", value: null, compare: true },
131299
+ colormap: { type: "string", value: GLSL_COLORMAP_DEFAULT, compare: true },
131300
+ expressionData: { type: "object", value: null, compare: true },
131301
+ multiFeatureValues: { type: "array", value: null, compare: true },
131302
+ setColorValues: { type: "array", value: null, compare: true },
131303
+ channelFeatureValueColormaps: { type: "array", value: null, compare: true },
131304
+ channelFeatureValueColormapRanges: { type: "array", value: null, compare: true },
131305
+ channelIsStaticColorMode: { type: "array", value: null, compare: true },
131306
+ channelIsSetColorMode: { type: "array", value: null, compare: true }
131307
+ };
131308
+ class BitmaskLayer2 extends XRLayer {
131309
+ // eslint-disable-next-line class-methods-use-this
131310
+ getShaders() {
131311
+ const { colormap } = this.props;
131312
+ return {
131313
+ fs,
131314
+ vs,
131315
+ modules: [project32, picking],
131316
+ defines: {
131317
+ [COLORMAP_SHADER_PLACEHOLDER]: GLSL_COLORMAPS.includes(colormap) ? colormap : GLSL_COLORMAP_DEFAULT
131318
+ }
131319
+ };
131320
+ }
131321
+ /**
131322
+ * Override the parent loadChannelTextures to enable
131323
+ * up to eight channels (rather than six).
131324
+ * Reference: https://github.com/hms-dbmi/viv/blob/v0.13.3/packages/layers/src/xr-layer/xr-layer.js#L316
131325
+ */
131326
+ loadChannelTextures(channelData) {
131327
+ const textures = {
131328
+ channel0: null,
131329
+ channel1: null,
131330
+ channel2: null,
131331
+ channel3: null,
131332
+ channel4: null,
131333
+ channel5: null,
131334
+ channel6: null
131335
+ };
131336
+ if (this.state.textures) {
131337
+ Object.values(this.state.textures).forEach((tex) => tex && tex.delete());
131338
+ }
131339
+ if (channelData && Object.keys(channelData).length > 0 && channelData.data) {
131340
+ channelData.data.forEach((d, i2) => {
131341
+ textures[`channel${i2}`] = this.dataToTexture(d, channelData.width, channelData.height);
131342
+ }, this);
131343
+ this.setState({ textures });
131344
+ }
131345
+ }
131346
+ updateState({ props: props2, oldProps, changeFlags }) {
131347
+ super.updateState({ props: props2, oldProps, changeFlags });
131348
+ if (props2.multiFeatureValues !== oldProps.multiFeatureValues || props2.setColorValues !== oldProps.setColorValues || props2.channelIsSetColorMode !== oldProps.channelIsSetColorMode) {
131349
+ const { multiFeatureValues, setColorValues, channelIsSetColorMode } = this.props;
131350
+ const [valueTex, colorTex, valueTexOffsets, colorTexOffsets, valueTexHeight, colorTexHeight] = this.multiSetsToTexture(multiFeatureValues, setColorValues, channelIsSetColorMode);
131351
+ this.setState({
131352
+ valueTex,
131353
+ colorTex,
131354
+ valueTexOffsets,
131355
+ colorTexOffsets,
131356
+ valueTexHeight,
131357
+ colorTexHeight
131358
+ });
131359
+ }
131360
+ if (props2.colormap !== oldProps.colormap) {
131361
+ const { gl } = this.context;
131362
+ if (this.state.model) {
131363
+ this.state.model.delete();
131364
+ }
131365
+ this.setState({ model: this._getModel(gl) });
131366
+ this.getAttributeManager().invalidateAll();
131367
+ }
131368
+ }
131369
+ draw(opts2) {
131370
+ const { uniforms } = opts2;
131371
+ const {
131372
+ channelStrokeWidths,
131373
+ channelsFilled,
131374
+ channelOpacities,
131375
+ channelColors,
131376
+ channelsVisible,
131377
+ // TODO: use `channelFeatureValueColormaps` in shader,
131378
+ // figure out how to call multiple GLSL colormap functions
131379
+ channelFeatureValueColormaps,
131380
+ channelFeatureValueColormapRanges,
131381
+ channelIsStaticColorMode,
131382
+ channelIsSetColorMode,
131383
+ hoveredCell,
131384
+ colorScaleLo,
131385
+ colorScaleHi,
131386
+ isExpressionMode,
131387
+ zoom,
131388
+ minZoom,
131389
+ maxZoom,
131390
+ zoomOffset
131391
+ // TODO: figure out if this needs to be used or not
131392
+ } = this.props;
131393
+ const {
131394
+ textures,
131395
+ model,
131396
+ // Expression and set index (and colors) textures with offsets
131397
+ valueTex,
131398
+ colorTex,
131399
+ valueTexOffsets,
131400
+ colorTexOffsets,
131401
+ valueTexHeight,
131402
+ colorTexHeight
131403
+ } = this.state;
131404
+ if (textures && model) {
131405
+ const scaleFactor = 1 / 2 ** (maxZoom - zoom);
131406
+ const colors = fromEntries(range$2(MAX_CHANNELS).map((i2) => [`color${i2}`, getColor(channelColors[i2])]));
131407
+ model.setUniforms(Object.assign({}, uniforms, {
131408
+ ...colors,
131409
+ // Bitmask image channel data textures
131410
+ ...textures,
131411
+ multiFeatureTexSize: MULTI_FEATURE_TEX_SIZE,
131412
+ // Expression textures with offsets
131413
+ valueTex,
131414
+ valueTexOffsets: padWithDefault(valueTexOffsets, 0, MAX_CHANNELS - valueTexOffsets.length),
131415
+ valueTexHeight,
131416
+ // Set indices and colors textures with offsets
131417
+ colorTex,
131418
+ colorTexOffsets: padWithDefault(colorTexOffsets, 0, MAX_CHANNELS - colorTexOffsets.length),
131419
+ colorTexHeight,
131420
+ // Visualization properties
131421
+ channelsFilled: padWithDefault(
131422
+ channelsFilled,
131423
+ true,
131424
+ // There are six texture entries on the shaders
131425
+ MAX_CHANNELS - channelsFilled.length
131426
+ ),
131427
+ channelOpacities: padWithDefault(
131428
+ channelOpacities,
131429
+ 0,
131430
+ // There are six texture entries on the shaders
131431
+ MAX_CHANNELS - channelOpacities.length
131432
+ ),
131433
+ channelStrokeWidths: padWithDefault(
131434
+ channelStrokeWidths,
131435
+ 1,
131436
+ // There are six texture entries on the shaders
131437
+ MAX_CHANNELS - channelStrokeWidths.length
131438
+ ),
131439
+ channelColormapRangeStarts: padWithDefault(
131440
+ channelFeatureValueColormapRanges.map((r2) => (r2 == null ? void 0 : r2[0]) || 0),
131441
+ 0,
131442
+ // There are six texture entries on the shaders
131443
+ MAX_CHANNELS - channelFeatureValueColormapRanges.length
131444
+ ),
131445
+ channelColormapRangeEnds: padWithDefault(
131446
+ channelFeatureValueColormapRanges.map((r2) => (r2 == null ? void 0 : r2[1]) || 1),
131447
+ 1,
131448
+ // There are six texture entries on the shaders
131449
+ MAX_CHANNELS - channelFeatureValueColormapRanges.length
131450
+ ),
131451
+ channelIsStaticColorMode: padWithDefault(
131452
+ channelIsStaticColorMode,
131453
+ true,
131454
+ // There are six texture entries on the shaders
131455
+ MAX_CHANNELS - channelIsStaticColorMode.length
131456
+ ),
131457
+ channelIsSetColorMode: padWithDefault(
131458
+ channelIsSetColorMode,
131459
+ false,
131460
+ // There are six texture entries on the shaders
131461
+ MAX_CHANNELS - channelIsSetColorMode.length
131462
+ ),
131463
+ hovered: hoveredCell || 0,
131464
+ channelsVisible: padWithDefault(
131465
+ channelsVisible,
131466
+ false,
131467
+ // There are six texture entries on the shaders
131468
+ MAX_CHANNELS - channelsVisible.length
131469
+ ),
131470
+ // uColorScaleRange: [colorScaleLo, colorScaleHi],
131471
+ // uIsExpressionMode: isExpressionMode,
131472
+ // uIsOutlined: false,
131473
+ scaleFactor
131474
+ })).draw();
131475
+ }
131476
+ }
131477
+ /**
131478
+ * This function creates textures from the data
131479
+ */
131480
+ dataToTexture(data, width, height) {
131481
+ const isWebGL2On = isWebGL2$1(this.context.gl);
131482
+ return new Texture2D(this.context.gl, {
131483
+ width,
131484
+ height,
131485
+ // Only use Float32 so we don't have to write two shaders
131486
+ data: new Float32Array(data),
131487
+ // we don't want or need mimaps
131488
+ mipmaps: false,
131489
+ parameters: {
131490
+ // NEAREST for integer data
131491
+ [GL$1.TEXTURE_MIN_FILTER]: GL$1.NEAREST,
131492
+ [GL$1.TEXTURE_MAG_FILTER]: GL$1.NEAREST,
131493
+ // CLAMP_TO_EDGE to remove tile artifacts
131494
+ [GL$1.TEXTURE_WRAP_S]: GL$1.CLAMP_TO_EDGE,
131495
+ [GL$1.TEXTURE_WRAP_T]: GL$1.CLAMP_TO_EDGE
131496
+ },
131497
+ format: isWebGL2On ? GL$1.R32F : GL$1.LUMINANCE,
131498
+ dataFormat: isWebGL2On ? GL$1.RED : GL$1.LUMINANCE,
131499
+ type: GL$1.FLOAT
131500
+ });
131501
+ }
131502
+ multiSetsToTexture(multiFeatureValues, setColorValues, channelIsSetColorMode) {
131503
+ const isWebGL2On = isWebGL2$1(this.context.gl);
131504
+ const [totalData, valueTexHeight, indicesOffsets, totalColors, colorTexHeight, colorsOffsets] = multiSetsToTextureData(multiFeatureValues, setColorValues, channelIsSetColorMode, MULTI_FEATURE_TEX_SIZE);
131505
+ return [
131506
+ // Color indices texture
131507
+ new Texture2D(this.context.gl, {
131508
+ width: MULTI_FEATURE_TEX_SIZE,
131509
+ height: valueTexHeight,
131510
+ // Only use Float32 so we don't have to write two shaders
131511
+ data: new Float32Array(totalData),
131512
+ // we don't want or need mimaps
131513
+ mipmaps: false,
131514
+ parameters: {
131515
+ // NEAREST for integer data
131516
+ [GL$1.TEXTURE_MIN_FILTER]: GL$1.NEAREST,
131517
+ [GL$1.TEXTURE_MAG_FILTER]: GL$1.NEAREST,
131518
+ // CLAMP_TO_EDGE to remove tile artifacts
131519
+ [GL$1.TEXTURE_WRAP_S]: GL$1.CLAMP_TO_EDGE,
131520
+ [GL$1.TEXTURE_WRAP_T]: GL$1.CLAMP_TO_EDGE
131521
+ },
131522
+ format: isWebGL2On ? GL$1.R32F : GL$1.LUMINANCE,
131523
+ dataFormat: isWebGL2On ? GL$1.RED : GL$1.LUMINANCE,
131524
+ type: GL$1.FLOAT
131525
+ }),
131526
+ // Colors texture
131527
+ new Texture2D(this.context.gl, {
131528
+ width: MULTI_FEATURE_TEX_SIZE,
131529
+ height: colorTexHeight,
131530
+ // Only use Float32 so we don't have to write two shaders
131531
+ data: new Float32Array(totalColors),
131532
+ // we don't want or need mimaps
131533
+ mipmaps: false,
131534
+ parameters: {
131535
+ // NEAREST for integer data
131536
+ [GL$1.TEXTURE_MIN_FILTER]: GL$1.NEAREST,
131537
+ [GL$1.TEXTURE_MAG_FILTER]: GL$1.NEAREST,
131538
+ // CLAMP_TO_EDGE to remove tile artifacts
131539
+ [GL$1.TEXTURE_WRAP_S]: GL$1.CLAMP_TO_EDGE,
131540
+ [GL$1.TEXTURE_WRAP_T]: GL$1.CLAMP_TO_EDGE
131541
+ },
131542
+ format: isWebGL2On ? GL$1.R32F : GL$1.LUMINANCE,
131543
+ dataFormat: isWebGL2On ? GL$1.RED : GL$1.LUMINANCE,
131544
+ type: GL$1.FLOAT
131545
+ }),
131546
+ // Offsets
131547
+ indicesOffsets,
131548
+ colorsOffsets,
131549
+ // Texture heights
131550
+ valueTexHeight,
131551
+ colorTexHeight
131552
+ ];
131553
+ }
131554
+ }
131555
+ BitmaskLayer2.layerName = "BitmaskLayer";
131556
+ BitmaskLayer2.defaultProps = defaultProps$1;
130896
131557
  function r(e2) {
130897
131558
  var t2, f2, n2 = "";
130898
131559
  if ("string" == typeof e2 || "number" == typeof e2)
@@ -141039,10 +141700,9 @@ class AbstractSpatialOrScatterplot extends PureComponent {
141039
141700
  const {
141040
141701
  setViewState,
141041
141702
  viewState,
141042
- layers,
141043
141703
  spatialAxisFixed
141044
141704
  } = this.props;
141045
- const use3d = layers == null ? void 0 : layers.some((l2) => l2.use3d);
141705
+ const use3d = this.use3d();
141046
141706
  setViewState({
141047
141707
  ...nextViewState,
141048
141708
  // If the axis is fixed, just use the current target in state i.e don't change target.
@@ -141090,6 +141750,8 @@ class AbstractSpatialOrScatterplot extends PureComponent {
141090
141750
  getLayers() {
141091
141751
  return [];
141092
141752
  }
141753
+ // TODO: remove this method and use the layer-level onHover instead.
141754
+ // (e.g., see delegateHover in spatial-beta/SpatialSubscriber.js).
141093
141755
  // eslint-disable-next-line consistent-return
141094
141756
  onHover(info) {
141095
141757
  const {
@@ -141236,7 +141898,8 @@ class AbstractSpatialOrScatterplot extends PureComponent {
141236
141898
  deckRef,
141237
141899
  viewState,
141238
141900
  uuid,
141239
- hideTools
141901
+ hideTools,
141902
+ orbitAxis
141240
141903
  } = this.props;
141241
141904
  const { gl, tool } = this.state;
141242
141905
  const layers = this.getLayers();
@@ -141263,7 +141926,7 @@ class AbstractSpatialOrScatterplot extends PureComponent {
141263
141926
  id: `deckgl-overlay-${uuid}`,
141264
141927
  ref: deckRef,
141265
141928
  views: [
141266
- use3d ? new OrbitView({ id: "orbit", controller: true, orbitAxis: "Y" }) : new OrthographicView({
141929
+ use3d ? new OrbitView({ id: "orbit", controller: true, orbitAxis }) : new OrthographicView({
141267
141930
  id: "ortho"
141268
141931
  })
141269
141932
  ],
@@ -141589,7 +142252,7 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
141589
142252
  }
141590
142253
  return result;
141591
142254
  }
141592
- createSelectionLayers() {
142255
+ createSelectionLayer() {
141593
142256
  const {
141594
142257
  obsEmbeddingIndex: obsIndex,
141595
142258
  obsEmbedding,
@@ -141600,14 +142263,20 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
141600
142263
  const { cellsQuadTree } = this;
141601
142264
  const flipYTooltip = true;
141602
142265
  const getCellCoords = makeDefaultGetObsCoords(obsEmbedding);
141603
- return getSelectionLayers(
142266
+ return getSelectionLayer(
141604
142267
  tool,
141605
142268
  viewState.zoom,
141606
142269
  CELLS_LAYER_ID,
141607
- getCellCoords,
141608
- obsIndex,
141609
- setCellSelection,
141610
- cellsQuadTree,
142270
+ [
142271
+ {
142272
+ getObsCoords: getCellCoords,
142273
+ obsIndex,
142274
+ obsQuadTree: cellsQuadTree,
142275
+ onSelect: (obsIds) => {
142276
+ setCellSelection(obsIds);
142277
+ }
142278
+ }
142279
+ ],
141611
142280
  flipYTooltip
141612
142281
  );
141613
142282
  }
@@ -141619,7 +142288,7 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
141619
142288
  return [
141620
142289
  cellsLayer,
141621
142290
  ...cellSetsLayers,
141622
- ...this.createSelectionLayers()
142291
+ this.createSelectionLayer()
141623
142292
  ];
141624
142293
  }
141625
142294
  onUpdateCellsData() {