@vitessce/spatial-utils 3.1.2 → 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.
@@ -62,12 +62,62 @@ function baseGetTag(value) {
62
62
  function isObjectLike$1(value) {
63
63
  return value != null && typeof value == "object";
64
64
  }
65
+ var symbolTag$4 = "[object Symbol]";
66
+ function isSymbol$1(value) {
67
+ return typeof value == "symbol" || isObjectLike$1(value) && baseGetTag(value) == symbolTag$4;
68
+ }
65
69
  var isArray$4 = Array.isArray;
66
70
  const isArray$5 = isArray$4;
71
+ var reWhitespace = /\s/;
72
+ function trimmedEndIndex(string) {
73
+ var index2 = string.length;
74
+ while (index2-- && reWhitespace.test(string.charAt(index2))) {
75
+ }
76
+ return index2;
77
+ }
78
+ var reTrimStart = /^\s+/;
79
+ function baseTrim(string) {
80
+ return string ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, "") : string;
81
+ }
67
82
  function isObject$5(value) {
68
83
  var type = typeof value;
69
84
  return value != null && (type == "object" || type == "function");
70
85
  }
86
+ var NAN$1 = 0 / 0;
87
+ var reIsBadHex$1 = /^[-+]0x[0-9a-f]+$/i;
88
+ var reIsBinary$1 = /^0b[01]+$/i;
89
+ var reIsOctal$1 = /^0o[0-7]+$/i;
90
+ var freeParseInt$1 = parseInt;
91
+ function toNumber$3(value) {
92
+ if (typeof value == "number") {
93
+ return value;
94
+ }
95
+ if (isSymbol$1(value)) {
96
+ return NAN$1;
97
+ }
98
+ if (isObject$5(value)) {
99
+ var other = typeof value.valueOf == "function" ? value.valueOf() : value;
100
+ value = isObject$5(other) ? other + "" : other;
101
+ }
102
+ if (typeof value != "string") {
103
+ return value === 0 ? value : +value;
104
+ }
105
+ value = baseTrim(value);
106
+ var isBinary2 = reIsBinary$1.test(value);
107
+ return isBinary2 || reIsOctal$1.test(value) ? freeParseInt$1(value.slice(2), isBinary2 ? 2 : 8) : reIsBadHex$1.test(value) ? NAN$1 : +value;
108
+ }
109
+ var INFINITY = 1 / 0, MAX_INTEGER = 17976931348623157e292;
110
+ function toFinite(value) {
111
+ if (!value) {
112
+ return value === 0 ? value : 0;
113
+ }
114
+ value = toNumber$3(value);
115
+ if (value === INFINITY || value === -INFINITY) {
116
+ var sign2 = value < 0 ? -1 : 1;
117
+ return sign2 * MAX_INTEGER;
118
+ }
119
+ return value === value ? value : 0;
120
+ }
71
121
  var asyncTag = "[object AsyncFunction]", funcTag$2 = "[object Function]", genTag$1 = "[object GeneratorFunction]", proxyTag = "[object Proxy]";
72
122
  function isFunction$3(value) {
73
123
  if (!isObject$5(value)) {
@@ -223,6 +273,16 @@ function isLength(value) {
223
273
  function isArrayLike(value) {
224
274
  return value != null && isLength(value.length) && !isFunction$3(value);
225
275
  }
276
+ function isIterateeCall(value, index2, object2) {
277
+ if (!isObject$5(object2)) {
278
+ return false;
279
+ }
280
+ var type = typeof index2;
281
+ if (type == "number" ? isArrayLike(object2) && isIndex$1(index2, object2.length) : type == "string" && index2 in object2) {
282
+ return eq$4(object2[index2], value);
283
+ }
284
+ return false;
285
+ }
226
286
  var objectProto$b = Object.prototype;
227
287
  function isPrototype(value) {
228
288
  var Ctor = value && value.constructor, proto = typeof Ctor == "function" && Ctor.prototype || objectProto$b;
@@ -1045,6 +1105,33 @@ function baseIsEqual(value, other, bitmask, customizer, stack2) {
1045
1105
  function isEqual$1(value, other) {
1046
1106
  return baseIsEqual(value, other);
1047
1107
  }
1108
+ var nativeCeil = Math.ceil, nativeMax$1 = Math.max;
1109
+ function baseRange(start, end, step, fromRight) {
1110
+ var index2 = -1, length2 = nativeMax$1(nativeCeil((end - start) / (step || 1)), 0), result = Array(length2);
1111
+ while (length2--) {
1112
+ result[fromRight ? length2 : ++index2] = start;
1113
+ start += step;
1114
+ }
1115
+ return result;
1116
+ }
1117
+ function createRange(fromRight) {
1118
+ return function(start, end, step) {
1119
+ if (step && typeof step != "number" && isIterateeCall(start, end, step)) {
1120
+ end = step = void 0;
1121
+ }
1122
+ start = toFinite(start);
1123
+ if (end === void 0) {
1124
+ end = start;
1125
+ start = 0;
1126
+ } else {
1127
+ end = toFinite(end);
1128
+ }
1129
+ step = step === void 0 ? start < end ? 1 : -1 : toFinite(step);
1130
+ return baseRange(start, end, step, fromRight);
1131
+ };
1132
+ }
1133
+ var range$4 = createRange();
1134
+ const range$5 = range$4;
1048
1135
  function assert$c(condition, message) {
1049
1136
  if (!condition) {
1050
1137
  throw new Error("math.gl assertion ".concat(message));
@@ -1800,7 +1887,7 @@ function negate(out, a2) {
1800
1887
  out[2] = -a2[2];
1801
1888
  return out;
1802
1889
  }
1803
- function normalize$3(out, a2) {
1890
+ function normalize$4(out, a2) {
1804
1891
  var x2 = a2[0];
1805
1892
  var y2 = a2[1];
1806
1893
  var z2 = a2[2];
@@ -3109,7 +3196,7 @@ function squaredLength$1(a2) {
3109
3196
  var w2 = a2[3];
3110
3197
  return x2 * x2 + y2 * y2 + z2 * z2 + w2 * w2;
3111
3198
  }
3112
- function normalize$2(out, a2) {
3199
+ function normalize$3(out, a2) {
3113
3200
  var x2 = a2[0];
3114
3201
  var y2 = a2[1];
3115
3202
  var z2 = a2[2];
@@ -3746,7 +3833,7 @@ var dot$2 = dot$3;
3746
3833
  var lerp$1 = lerp$2;
3747
3834
  var length$2 = length$3;
3748
3835
  var squaredLength = squaredLength$1;
3749
- var normalize$1 = normalize$2;
3836
+ var normalize$2 = normalize$3;
3750
3837
  var rotationTo = function() {
3751
3838
  var tmpvec3 = create$3();
3752
3839
  var xUnitVec3 = fromValues(1, 0, 0);
@@ -3757,7 +3844,7 @@ var rotationTo = function() {
3757
3844
  cross$1(tmpvec3, xUnitVec3, a2);
3758
3845
  if (len(tmpvec3) < 1e-6)
3759
3846
  cross$1(tmpvec3, yUnitVec3, a2);
3760
- normalize$3(tmpvec3, tmpvec3);
3847
+ normalize$4(tmpvec3, tmpvec3);
3761
3848
  setAxisAngle(out, tmpvec3, Math.PI);
3762
3849
  return out;
3763
3850
  } else if (dot2 > 0.999999) {
@@ -3772,7 +3859,7 @@ var rotationTo = function() {
3772
3859
  out[1] = tmpvec3[1];
3773
3860
  out[2] = tmpvec3[2];
3774
3861
  out[3] = 1 + dot2;
3775
- return normalize$1(out, out);
3862
+ return normalize$2(out, out);
3776
3863
  }
3777
3864
  };
3778
3865
  }();
@@ -3798,7 +3885,7 @@ var rotationTo = function() {
3798
3885
  matr[2] = -view[0];
3799
3886
  matr[5] = -view[1];
3800
3887
  matr[8] = -view[2];
3801
- return normalize$1(out, fromMat3(out, matr));
3888
+ return normalize$2(out, fromMat3(out, matr));
3802
3889
  };
3803
3890
  })();
3804
3891
  const IDENTITY_QUATERNION = [0, 0, 0, 1];
@@ -28415,8 +28502,10 @@ const ViewType$1 = {
28415
28502
  STATUS: "status",
28416
28503
  SCATTERPLOT: "scatterplot",
28417
28504
  SPATIAL: "spatial",
28505
+ SPATIAL_BETA: "spatialBeta",
28418
28506
  HEATMAP: "heatmap",
28419
28507
  LAYER_CONTROLLER: "layerController",
28508
+ LAYER_CONTROLLER_BETA: "layerControllerBeta",
28420
28509
  GENOMIC_PROFILES: "genomicProfiles",
28421
28510
  GATING: "gating",
28422
28511
  FEATURE_LIST: "featureList",
@@ -28428,20 +28517,24 @@ const ViewType$1 = {
28428
28517
  const DataType$2 = {
28429
28518
  OBS_LABELS: "obsLabels",
28430
28519
  OBS_EMBEDDING: "obsEmbedding",
28431
- OBS_LOCATIONS: "obsLocations",
28432
28520
  OBS_FEATURE_MATRIX: "obsFeatureMatrix",
28433
28521
  OBS_SETS: "obsSets",
28434
28522
  FEATURE_LABELS: "featureLabels",
28435
28523
  IMAGE: "image",
28436
28524
  OBS_SEGMENTATIONS: "obsSegmentations",
28437
28525
  NEIGHBORHOODS: "neighborhoods",
28438
- GENOMIC_PROFILES: "genomic-profiles"
28526
+ GENOMIC_PROFILES: "genomic-profiles",
28527
+ OBS_SPOTS: "obsSpots",
28528
+ OBS_POINTS: "obsPoints",
28529
+ OBS_LOCATIONS: "obsLocations"
28439
28530
  };
28440
28531
  const FileType$1 = {
28441
28532
  // Joint file types
28442
28533
  ANNDATA_ZARR: "anndata.zarr",
28443
28534
  // Atomic file types
28444
28535
  OBS_EMBEDDING_CSV: "obsEmbedding.csv",
28536
+ OBS_SPOTS_CSV: "obsSpots.csv",
28537
+ OBS_POINTS_CSV: "obsPoints.csv",
28445
28538
  OBS_LOCATIONS_CSV: "obsLocations.csv",
28446
28539
  OBS_LABELS_CSV: "obsLabels.csv",
28447
28540
  FEATURE_LABELS_CSV: "featureLabels.csv",
@@ -28454,6 +28547,8 @@ const FileType$1 = {
28454
28547
  OBS_FEATURE_MATRIX_ANNDATA_ZARR: "obsFeatureMatrix.anndata.zarr",
28455
28548
  OBS_SETS_ANNDATA_ZARR: "obsSets.anndata.zarr",
28456
28549
  OBS_EMBEDDING_ANNDATA_ZARR: "obsEmbedding.anndata.zarr",
28550
+ OBS_SPOTS_ANNDATA_ZARR: "obsSpots.anndata.zarr",
28551
+ OBS_POINTS_ANNDATA_ZARR: "obsPoints.anndata.zarr",
28457
28552
  OBS_LOCATIONS_ANNDATA_ZARR: "obsLocations.anndata.zarr",
28458
28553
  OBS_SEGMENTATIONS_ANNDATA_ZARR: "obsSegmentations.anndata.zarr",
28459
28554
  OBS_LABELS_ANNDATA_ZARR: "obsLabels.anndata.zarr",
@@ -28462,6 +28557,8 @@ const FileType$1 = {
28462
28557
  OBS_FEATURE_MATRIX_MUDATA_ZARR: "obsFeatureMatrix.mudata.zarr",
28463
28558
  OBS_SETS_MUDATA_ZARR: "obsSets.mudata.zarr",
28464
28559
  OBS_EMBEDDING_MUDATA_ZARR: "obsEmbedding.mudata.zarr",
28560
+ OBS_SPOTS_MUDATA_ZARR: "obsSpots.mudata.zarr",
28561
+ OBS_POINTS_MUDATA_ZARR: "obsPoints.mudata.zarr",
28465
28562
  OBS_LOCATIONS_MUDATA_ZARR: "obsLocations.mudata.zarr",
28466
28563
  OBS_SEGMENTATIONS_MUDATA_ZARR: "obsSegmentations.mudata.zarr",
28467
28564
  OBS_LABELS_MUDATA_ZARR: "obsLabels.mudata.zarr",
@@ -28505,10 +28602,8 @@ const FileType$1 = {
28505
28602
  ANNDATA_EXPRESSION_MATRIX_ZARR: "anndata-expression-matrix.zarr"
28506
28603
  };
28507
28604
  const CoordinationType$1 = {
28508
- // Meta coordination scopes
28509
28605
  META_COORDINATION_SCOPES: "metaCoordinationScopes",
28510
28606
  META_COORDINATION_SCOPES_BY: "metaCoordinationScopesBy",
28511
- // Other coordination scopes
28512
28607
  DATASET: "dataset",
28513
28608
  // Entity types
28514
28609
  OBS_TYPE: "obsType",
@@ -28534,6 +28629,7 @@ const CoordinationType$1 = {
28534
28629
  SPATIAL_TARGET_X: "spatialTargetX",
28535
28630
  SPATIAL_TARGET_Y: "spatialTargetY",
28536
28631
  SPATIAL_TARGET_Z: "spatialTargetZ",
28632
+ SPATIAL_TARGET_T: "spatialTargetT",
28537
28633
  SPATIAL_ROTATION_X: "spatialRotationX",
28538
28634
  SPATIAL_ROTATION_Y: "spatialRotationY",
28539
28635
  SPATIAL_ROTATION_Z: "spatialRotationZ",
@@ -28571,7 +28667,46 @@ const CoordinationType$1 = {
28571
28667
  GATING_FEATURE_SELECTION_X: "gatingFeatureSelectionX",
28572
28668
  GATING_FEATURE_SELECTION_Y: "gatingFeatureSelectionY",
28573
28669
  FEATURE_VALUE_TRANSFORM_COEFFICIENT: "featureValueTransformCoefficient",
28574
- TOOLTIPS_VISIBLE: "tooltipsVisible"
28670
+ TOOLTIPS_VISIBLE: "tooltipsVisible",
28671
+ FILE_UID: "fileUid",
28672
+ IMAGE_LAYER: "imageLayer",
28673
+ IMAGE_CHANNEL: "imageChannel",
28674
+ SEGMENTATION_LAYER: "segmentationLayer",
28675
+ SEGMENTATION_CHANNEL: "segmentationChannel",
28676
+ SPATIAL_TARGET_C: "spatialTargetC",
28677
+ SPATIAL_LAYER_VISIBLE: "spatialLayerVisible",
28678
+ SPATIAL_LAYER_OPACITY: "spatialLayerOpacity",
28679
+ SPATIAL_LAYER_COLORMAP: "spatialLayerColormap",
28680
+ SPATIAL_LAYER_TRANSPARENT_COLOR: "spatialLayerTransparentColor",
28681
+ SPATIAL_LAYER_MODEL_MATRIX: "spatialLayerModelMatrix",
28682
+ SPATIAL_SEGMENTATION_FILLED: "spatialSegmentationFilled",
28683
+ SPATIAL_SEGMENTATION_STROKE_WIDTH: "spatialSegmentationStrokeWidth",
28684
+ SPATIAL_CHANNEL_COLOR: "spatialChannelColor",
28685
+ SPATIAL_CHANNEL_VISIBLE: "spatialChannelVisible",
28686
+ SPATIAL_CHANNEL_OPACITY: "spatialChannelOpacity",
28687
+ SPATIAL_CHANNEL_WINDOW: "spatialChannelWindow",
28688
+ PHOTOMETRIC_INTERPRETATION: "photometricInterpretation",
28689
+ // For 3D volume rendering
28690
+ SPATIAL_RENDERING_MODE: "spatialRenderingMode",
28691
+ VOLUMETRIC_RENDERING_ALGORITHM: "volumetricRenderingAlgorithm",
28692
+ SPATIAL_TARGET_RESOLUTION: "spatialTargetResolution",
28693
+ // For clipping plane sliders
28694
+ SPATIAL_SLICE_X: "spatialSliceX",
28695
+ SPATIAL_SLICE_Y: "spatialSliceY",
28696
+ SPATIAL_SLICE_Z: "spatialSliceZ",
28697
+ // For spatial spot and point layers
28698
+ SPOT_LAYER: "spotLayer",
28699
+ POINT_LAYER: "pointLayer",
28700
+ SPATIAL_SPOT_RADIUS: "spatialSpotRadius",
28701
+ SPATIAL_SPOT_FILLED: "spatialSpotFilled",
28702
+ SPATIAL_SPOT_STROKE_WIDTH: "spatialSpotStrokeWidth",
28703
+ SPATIAL_LAYER_COLOR: "spatialLayerColor",
28704
+ PIXEL_HIGHLIGHT: "pixelHighlight",
28705
+ TOOLTIP_CROSSHAIRS_VISIBLE: "tooltipCrosshairsVisible",
28706
+ LEGEND_VISIBLE: "legendVisible",
28707
+ SPATIAL_CHANNEL_LABELS_VISIBLE: "spatialChannelLabelsVisible",
28708
+ SPATIAL_CHANNEL_LABELS_ORIENTATION: "spatialChannelLabelsOrientation",
28709
+ SPATIAL_CHANNEL_LABEL_SIZE: "spatialChannelLabelSize"
28575
28710
  };
28576
28711
  const ViewType = {
28577
28712
  GENES: [
@@ -28832,6 +28967,8 @@ const annDataObsSets = z.array(z.object({
28832
28967
  ]),
28833
28968
  scorePath: z.string().optional().describe("The location in the AnnData store for the set confidence scores, like 'obs/celltype_prediction_score.'")
28834
28969
  }));
28970
+ const annDataObsSpots = annDataObsm;
28971
+ const annDataObsPoints = annDataObsm;
28835
28972
  const annDataObsLocations = annDataObsm;
28836
28973
  const annDataObsEmbedding = annDataObsm;
28837
28974
  const annDataObsSegmentations = annDataObs;
@@ -28858,10 +28995,21 @@ z.object({
28858
28995
  z.object({
28859
28996
  obsIndex: z.string(),
28860
28997
  obsEmbedding: z.array(z.string()).length(2)
28998
+ // TODO: support 3D?
28999
+ });
29000
+ z.object({
29001
+ obsIndex: z.string(),
29002
+ obsSpots: z.array(z.string()).length(2)
29003
+ // TODO: support 3D?
29004
+ });
29005
+ z.object({
29006
+ obsIndex: z.string(),
29007
+ obsPoints: z.array(z.string()).length(3)
28861
29008
  });
28862
29009
  z.object({
28863
29010
  obsIndex: z.string(),
28864
29011
  obsLocations: z.array(z.string()).length(2)
29012
+ // TODO: support 3D?
28865
29013
  });
28866
29014
  z.object({
28867
29015
  obsIndex: z.string(),
@@ -28893,6 +29041,8 @@ z.object({
28893
29041
  ]),
28894
29042
  obsFeatureMatrix: annDataObsFeatureMatrix,
28895
29043
  obsSets: annDataObsSets,
29044
+ obsSpots: annDataObsSpots,
29045
+ obsPoints: annDataObsPoints,
28896
29046
  obsLocations: annDataObsLocations,
28897
29047
  obsSegmentations: annDataObsSegmentations,
28898
29048
  obsEmbedding: z.union([
@@ -33975,7 +34125,7 @@ var json2csv_umd = { exports: {} };
33975
34125
  var commonjsGlobal$1 = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof commonjsGlobal !== "undefined" ? commonjsGlobal : typeof self !== "undefined" ? self : {};
33976
34126
  var FUNC_ERROR_TEXT2 = "Expected a function";
33977
34127
  var HASH_UNDEFINED2 = "__lodash_hash_undefined__";
33978
- var INFINITY = 1 / 0;
34128
+ var INFINITY2 = 1 / 0;
33979
34129
  var funcTag2 = "[object Function]", genTag2 = "[object GeneratorFunction]", symbolTag2 = "[object Symbol]";
33980
34130
  var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/, reLeadingDot = /^\./, rePropName2 = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;
33981
34131
  var reRegExpChar2 = /[\\^$.*+?()[\]{}|]/g;
@@ -34158,7 +34308,7 @@ var json2csv_umd = { exports: {} };
34158
34308
  return symbolToString ? symbolToString.call(value) : "";
34159
34309
  }
34160
34310
  var result = value + "";
34161
- return result == "0" && 1 / value == -INFINITY ? "-0" : result;
34311
+ return result == "0" && 1 / value == -INFINITY2 ? "-0" : result;
34162
34312
  }
34163
34313
  function castPath(value) {
34164
34314
  return isArray$22(value) ? value : stringToPath3(value);
@@ -34204,7 +34354,7 @@ var json2csv_umd = { exports: {} };
34204
34354
  return value;
34205
34355
  }
34206
34356
  var result = value + "";
34207
- return result == "0" && 1 / value == -INFINITY ? "-0" : result;
34357
+ return result == "0" && 1 / value == -INFINITY2 ? "-0" : result;
34208
34358
  }
34209
34359
  function toSource2(func) {
34210
34360
  if (func != null) {
@@ -36829,17 +36979,17 @@ let COLOR;
36829
36979
  COLOR2[COLOR2["BRIGHT_CYAN"] = 96] = "BRIGHT_CYAN";
36830
36980
  COLOR2[COLOR2["BRIGHT_WHITE"] = 97] = "BRIGHT_WHITE";
36831
36981
  })(COLOR || (COLOR = {}));
36832
- function getColor(color) {
36982
+ function getColor$1(color) {
36833
36983
  return typeof color === "string" ? COLOR[color.toUpperCase()] || COLOR.WHITE : color;
36834
36984
  }
36835
36985
  function addColor(string, color, background) {
36836
36986
  if (!isBrowser$1 && typeof string === "string") {
36837
36987
  if (color) {
36838
- color = getColor(color);
36988
+ color = getColor$1(color);
36839
36989
  string = "\x1B[".concat(color, "m").concat(string, "\x1B[39m");
36840
36990
  }
36841
36991
  if (background) {
36842
- color = getColor(background);
36992
+ color = getColor$1(background);
36843
36993
  string = "\x1B[".concat(background + 10, "m").concat(string, "\x1B[49m");
36844
36994
  }
36845
36995
  }
@@ -66949,7 +67099,7 @@ function copyFlatRing(target, targetStartIndex, positions, size2, srcStartIndex
66949
67099
  modifyPolygonWindingDirection(target, windingDirection, windingOptions);
66950
67100
  return targetIndex;
66951
67101
  }
66952
- function normalize(polygon2, positionSize) {
67102
+ function normalize$1(polygon2, positionSize) {
66953
67103
  validate(polygon2);
66954
67104
  const positions = [];
66955
67105
  const holeIndices = [];
@@ -67055,7 +67205,7 @@ class PolygonTesselator extends Tesselator {
67055
67205
  }
67056
67206
  normalizeGeometry(polygon2) {
67057
67207
  if (this.normalize) {
67058
- const normalizedPolygon = normalize(polygon2, this.positionSize);
67208
+ const normalizedPolygon = normalize$1(polygon2, this.positionSize);
67059
67209
  if (this.opts.resolution) {
67060
67210
  return cutPolygonByGrid(getPositions(normalizedPolygon), getHoleIndices(normalizedPolygon), {
67061
67211
  size: this.positionSize,
@@ -67677,7 +67827,7 @@ class PolygonLayer extends CompositeLayer {
67677
67827
  objectInfo.index++;
67678
67828
  let polygon2 = getPolygon(object2, objectInfo);
67679
67829
  if (_normalize) {
67680
- polygon2 = normalize(polygon2, positionSize);
67830
+ polygon2 = normalize$1(polygon2, positionSize);
67681
67831
  }
67682
67832
  const {
67683
67833
  holeIndices
@@ -111504,7 +111654,7 @@ function clipExtent(x02, y02, x12, y12) {
111504
111654
  return clipStream;
111505
111655
  };
111506
111656
  }
111507
- function extent() {
111657
+ function extent$1() {
111508
111658
  var x02 = 0, y02 = 0, x12 = 960, y12 = 500, cache2, cacheStream, clip2;
111509
111659
  return clip2 = {
111510
111660
  stream: function(stream) {
@@ -112911,7 +113061,7 @@ const d3Geo$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
112911
113061
  geoBounds: bounds,
112912
113062
  geoCentroid: centroid$3,
112913
113063
  geoCircle: circle$2,
112914
- geoClipExtent: extent,
113064
+ geoClipExtent: extent$1,
112915
113065
  geoConicConformal: conicConformal,
112916
113066
  geoConicConformalRaw: conicConformalRaw,
112917
113067
  geoConicEqualArea: conicEqualArea,
@@ -132114,28 +132264,38 @@ const PASS_THROUGH_PROPS = [
132114
132264
  ];
132115
132265
  class SelectionLayer extends CompositeLayer {
132116
132266
  _selectPolygonObjects(coordinates2) {
132117
- const { onSelect, getCellCoords, cellsQuadTree, flipY } = this.props;
132267
+ const { flipY, obsLayers } = this.props;
132118
132268
  const flippedCoordinates = flipY ? coordinates2.map((poly) => poly.map((p) => [p[0], -p[1]])) : coordinates2;
132119
132269
  const selectedPolygon = polygon(flippedCoordinates);
132120
- const pickingInfos = [];
132121
- cellsQuadTree.visit((node2, x02, y02, x12, y12) => {
132122
- const nodePoints = [[[x02, y02], [x12, y02], [x12, y12], [x02, y12], [x02, y02]]];
132123
- const nodePolygon = polygon(nodePoints);
132124
- const nodePolygonContainsSelectedPolygon = booleanContains(nodePolygon, selectedPolygon);
132125
- const nodePolygonWithinSelectedPolygon = booleanWithin(nodePolygon, selectedPolygon);
132126
- const nodePolygonOverlapsSelectedPolgyon = booleanOverlap(nodePolygon, selectedPolygon);
132127
- if (!nodePolygonContainsSelectedPolygon && !nodePolygonWithinSelectedPolygon && !nodePolygonOverlapsSelectedPolgyon) {
132128
- return true;
132129
- }
132130
- if (node2.data && booleanPointInPolygon$1(point([].slice.call(getCellCoords(node2.data))), selectedPolygon)) {
132131
- pickingInfos.push(node2.data);
132132
- }
132133
- return false;
132270
+ obsLayers.forEach((obsLayer) => {
132271
+ const { getObsCoords, obsQuadTree, obsIndex, onSelect: layerOnSelect } = obsLayer;
132272
+ const pickingInfos = [];
132273
+ obsQuadTree == null ? void 0 : obsQuadTree.visit((node2, x02, y02, x12, y12) => {
132274
+ const nodePoints = [[[x02, y02], [x12, y02], [x12, y12], [x02, y12], [x02, y02]]];
132275
+ const nodePolygon = polygon(nodePoints);
132276
+ const nodePolygonContainsSelectedPolygon = booleanContains(nodePolygon, selectedPolygon);
132277
+ const nodePolygonWithinSelectedPolygon = booleanWithin(nodePolygon, selectedPolygon);
132278
+ const nodePolygonOverlapsSelectedPolgyon = booleanOverlap(nodePolygon, selectedPolygon);
132279
+ if (!nodePolygonContainsSelectedPolygon && !nodePolygonWithinSelectedPolygon && !nodePolygonOverlapsSelectedPolgyon) {
132280
+ return true;
132281
+ }
132282
+ if (node2.data && booleanPointInPolygon$1(point([].slice.call(getObsCoords(node2.data))), selectedPolygon)) {
132283
+ pickingInfos.push(node2.data);
132284
+ }
132285
+ return false;
132286
+ });
132287
+ const pickingIds = pickingInfos.map((obsI) => obsIndex[obsI]);
132288
+ layerOnSelect(pickingIds);
132289
+ });
132290
+ }
132291
+ _selectEmpty() {
132292
+ const { obsLayers } = this.props;
132293
+ obsLayers.forEach((obsLayer) => {
132294
+ const { onSelect: layerOnSelect } = obsLayer;
132295
+ layerOnSelect([]);
132134
132296
  });
132135
- onSelect({ pickingInfos });
132136
132297
  }
132137
132298
  renderLayers() {
132138
- const { onSelect } = this.props;
132139
132299
  const mode = MODE_MAP[this.props.selectionType] || distEs6.ViewMode;
132140
132300
  const inheritedProps = {};
132141
132301
  PASS_THROUGH_PROPS.forEach((p) => {
@@ -132157,7 +132317,7 @@ class SelectionLayer extends CompositeLayer {
132157
132317
  const { coordinates: coordinates2 } = updatedData.features[0].geometry;
132158
132318
  this._selectPolygonObjects(coordinates2);
132159
132319
  } else if (editType === EDIT_TYPE_CLEAR) {
132160
- onSelect({ pickingInfos: [] });
132320
+ this._selectEmpty();
132161
132321
  }
132162
132322
  },
132163
132323
  _subLayerProps: {
@@ -133297,16 +133457,16 @@ function addDecoder(cases, importFn) {
133297
133457
  }
133298
133458
  cases.forEach((c) => registry$1.set(c, importFn));
133299
133459
  }
133300
- addDecoder([void 0, 1], () => import("./raw-8e22b1c4.js").then((m) => m.default));
133301
- addDecoder(5, () => import("./lzw-c3783269.js").then((m) => m.default));
133460
+ addDecoder([void 0, 1], () => import("./raw-446b6beb.js").then((m) => m.default));
133461
+ addDecoder(5, () => import("./lzw-c5e8dff0.js").then((m) => m.default));
133302
133462
  addDecoder(6, () => {
133303
133463
  throw new Error("old style JPEG compression is not supported.");
133304
133464
  });
133305
- addDecoder(7, () => import("./jpeg-d67d9d82.js").then((m) => m.default));
133306
- addDecoder([8, 32946], () => import("./deflate-6fd0bca9.js").then((m) => m.default));
133307
- addDecoder(32773, () => import("./packbits-209c03d7.js").then((m) => m.default));
133308
- addDecoder(34887, () => import("./lerc-522345a3.js").then((m) => m.default));
133309
- addDecoder(50001, () => import("./webimage-a5d2769c.js").then((m) => m.default));
133465
+ addDecoder(7, () => import("./jpeg-76bff48f.js").then((m) => m.default));
133466
+ addDecoder([8, 32946], () => import("./deflate-3240dc7e.js").then((m) => m.default));
133467
+ addDecoder(32773, () => import("./packbits-ccf26149.js").then((m) => m.default));
133468
+ addDecoder(34887, () => import("./lerc-1ad8fc7c.js").then((m) => m.default));
133469
+ addDecoder(50001, () => import("./webimage-bf1c5425.js").then((m) => m.default));
133310
133470
  function decodeRowAcc(row, stride) {
133311
133471
  let length2 = row.length - stride;
133312
133472
  let offset = 0;
@@ -140201,7 +140361,7 @@ const SIGNAL_ABORTED = "__vivSignalAborted";
140201
140361
  addDecoder(5, () => LZWDecoder);
140202
140362
  const MAX_COLOR_INTENSITY = 255;
140203
140363
  const DEFAULT_COLOR_OFF = [0, 0, 0];
140204
- const MAX_CHANNELS = 6;
140364
+ const MAX_CHANNELS$1 = 6;
140205
140365
  const DEFAULT_FONT_FAMILY = "-apple-system, 'Helvetica Neue', Arial, sans-serif";
140206
140366
  const DTYPE_VALUES = {
140207
140367
  Uint8: {
@@ -141723,7 +141883,7 @@ const AdditiveColormapExtension = class extends LayerExtension {
141723
141883
  };
141724
141884
  AdditiveColormapExtension.extensionName = "AdditiveColormapExtension";
141725
141885
  AdditiveColormapExtension.defaultProps = defaultProps$4$1;
141726
- const fs$1$1 = `uniform vec3 transparentColor;
141886
+ const fs$1$2 = `uniform vec3 transparentColor;
141727
141887
  uniform bool useTransparentColor;
141728
141888
  uniform float opacity;
141729
141889
 
@@ -141750,12 +141910,12 @@ rgba = apply_opacity(rgb);
141750
141910
  `;
141751
141911
  const colorPalette = {
141752
141912
  name: "color-palette-module",
141753
- fs: fs$1$1,
141913
+ fs: fs$1$2,
141754
141914
  inject: {
141755
141915
  "fs:DECKGL_MUTATE_COLOR": DECKGL_MUTATE_COLOR
141756
141916
  }
141757
141917
  };
141758
- function padWithDefault$2(arr, defaultValue2, padWidth) {
141918
+ function padWithDefault$3(arr, defaultValue2, padWidth) {
141759
141919
  for (let i2 = 0; i2 < padWidth; i2 += 1) {
141760
141920
  arr.push(defaultValue2);
141761
141921
  }
@@ -141781,8 +141941,8 @@ function padColors({ colors, channelsVisible }) {
141781
141941
  const newColors = colors.map(
141782
141942
  (color, i2) => channelsVisible[i2] ? color.map((c) => c / MAX_COLOR_INTENSITY) : DEFAULT_COLOR_OFF
141783
141943
  );
141784
- const padSize = MAX_CHANNELS - newColors.length;
141785
- const paddedColors = padWithDefault$2(
141944
+ const padSize = MAX_CHANNELS$1 - newColors.length;
141945
+ const paddedColors = padWithDefault$3(
141786
141946
  newColors,
141787
141947
  DEFAULT_COLOR_OFF,
141788
141948
  padSize
@@ -142026,7 +142186,7 @@ vec4 colormap(float intensity, float opacity) {
142026
142186
  fs: fs2
142027
142187
  };
142028
142188
  }
142029
- const defaultProps$1$1 = {
142189
+ const defaultProps$1$2 = {
142030
142190
  colormap: { type: "string", value: "viridis", compare: true }
142031
142191
  };
142032
142192
  const BaseExtension$1 = class extends LayerExtension {
@@ -142036,7 +142196,7 @@ const BaseExtension$1 = class extends LayerExtension {
142036
142196
  }
142037
142197
  getShaders() {
142038
142198
  var _a2;
142039
- const name2 = ((_a2 = this == null ? void 0 : this.props) == null ? void 0 : _a2.colormap) || defaultProps$1$1.colormap.value;
142199
+ const name2 = ((_a2 = this == null ? void 0 : this.props) == null ? void 0 : _a2.colormap) || defaultProps$1$2.colormap.value;
142040
142200
  const apply_cmap = cmaps[name2];
142041
142201
  return {
142042
142202
  ...super.getShaders(),
@@ -142055,7 +142215,7 @@ const BaseExtension$1 = class extends LayerExtension {
142055
142215
  }
142056
142216
  };
142057
142217
  BaseExtension$1.extensionName = "BaseExtension";
142058
- BaseExtension$1.defaultProps = defaultProps$1$1;
142218
+ BaseExtension$1.defaultProps = defaultProps$1$2;
142059
142219
  const _BEFORE_RENDER$5 = "";
142060
142220
  const _RENDER$5 = ` float intensityArray[6] = float[6](intensityValue0, intensityValue1, intensityValue2, intensityValue3, intensityValue4, intensityValue5);
142061
142221
  float total = 0.0;
@@ -142254,7 +142414,7 @@ const channels = {
142254
142414
  function range(len2) {
142255
142415
  return [...Array(len2).keys()];
142256
142416
  }
142257
- function padWithDefault$1(arr, defaultValue2, padWidth) {
142417
+ function padWithDefault$2(arr, defaultValue2, padWidth) {
142258
142418
  for (let i2 = 0; i2 < padWidth; i2 += 1) {
142259
142419
  arr.push(defaultValue2);
142260
142420
  }
@@ -142278,20 +142438,20 @@ function padContrastLimits({
142278
142438
  const newContrastLimits = contrastLimits.map(
142279
142439
  (slider, i2) => channelsVisible[i2] ? slider : [maxSliderValue, maxSliderValue]
142280
142440
  );
142281
- const padSize = MAX_CHANNELS - newContrastLimits.length;
142441
+ const padSize = MAX_CHANNELS$1 - newContrastLimits.length;
142282
142442
  if (padSize < 0) {
142283
142443
  throw Error(
142284
142444
  `${newContrastLimits.lengths} channels passed in, but only 6 are allowed.`
142285
142445
  );
142286
142446
  }
142287
- const paddedContrastLimits = padWithDefault$1(
142447
+ const paddedContrastLimits = padWithDefault$2(
142288
142448
  newContrastLimits,
142289
142449
  [maxSliderValue, maxSliderValue],
142290
142450
  padSize
142291
142451
  ).reduce((acc, val) => acc.concat(val), []);
142292
142452
  return paddedContrastLimits;
142293
142453
  }
142294
- function getPhysicalSizeScalingMatrix(loader) {
142454
+ function getPhysicalSizeScalingMatrix$1(loader) {
142295
142455
  var _a2;
142296
142456
  const { x: x2, y: y2, z: z2 } = ((_a2 = loader == null ? void 0 : loader.meta) == null ? void 0 : _a2.physicalSizes) ?? {};
142297
142457
  if ((x2 == null ? void 0 : x2.size) && (y2 == null ? void 0 : y2.size) && (z2 == null ? void 0 : z2.size)) {
@@ -142314,7 +142474,7 @@ function makeBoundingBox(viewState) {
142314
142474
  viewport.unproject([0, viewport.height])
142315
142475
  ];
142316
142476
  }
142317
- const fs$1 = `#define SHADER_NAME xr-layer-fragment-shader
142477
+ const fs$1$1 = `#define SHADER_NAME xr-layer-fragment-shader
142318
142478
 
142319
142479
  precision highp float;
142320
142480
  precision highp int;
@@ -142355,7 +142515,7 @@ void main() {
142355
142515
  DECKGL_FILTER_COLOR(gl_FragColor, geometry);
142356
142516
  }
142357
142517
  `;
142358
- const vs$1 = `#define SHADER_NAME xr-layer-vertex-shader
142518
+ const vs$1$1 = `#define SHADER_NAME xr-layer-vertex-shader
142359
142519
 
142360
142520
  attribute vec2 texCoords;
142361
142521
  attribute vec3 positions;
@@ -142374,7 +142534,7 @@ void main(void) {
142374
142534
  DECKGL_FILTER_COLOR(color, geometry);
142375
142535
  }
142376
142536
  `;
142377
- const coreShaderModule = { fs: fs$1, vs: vs$1 };
142537
+ const coreShaderModule = { fs: fs$1$1, vs: vs$1$1 };
142378
142538
  function validateWebGL2Filter(gl, interpolation) {
142379
142539
  const canShowFloat = hasFeature(gl, FEATURES$1.TEXTURE_FLOAT);
142380
142540
  const canShowLinear = hasFeature(gl, FEATURES$1.TEXTURE_FILTER_LINEAR_FLOAT);
@@ -143465,7 +143625,7 @@ const CUBE_STRIP = [
143465
143625
  0
143466
143626
  ];
143467
143627
  const NUM_PLANES_DEFAULT = 1;
143468
- const defaultProps$1 = {
143628
+ const defaultProps$1$1 = {
143469
143629
  pickable: false,
143470
143630
  coordinateSystem: COORDINATE_SYSTEM.CARTESIAN,
143471
143631
  channelData: { type: "object", value: {}, compare: true },
@@ -143607,7 +143767,7 @@ const XR3DLayer = class extends Layer {
143607
143767
  });
143608
143768
  const invertedScaleMatrix = scaleMatrix.clone().invert();
143609
143769
  const invertedResolutionMatrix = resolutionMatrix.clone().invert();
143610
- const paddedClippingPlanes = padWithDefault$1(
143770
+ const paddedClippingPlanes = padWithDefault$2(
143611
143771
  clippingPlanes.map(
143612
143772
  (p) => p.clone().transform(invertedScaleMatrix).transform(invertedResolutionMatrix)
143613
143773
  ),
@@ -143697,7 +143857,7 @@ const XR3DLayer = class extends Layer {
143697
143857
  }
143698
143858
  };
143699
143859
  XR3DLayer.layerName = "XR3DLayer";
143700
- XR3DLayer.defaultProps = defaultProps$1;
143860
+ XR3DLayer.defaultProps = defaultProps$1$1;
143701
143861
  async function getVolume({
143702
143862
  source,
143703
143863
  selection,
@@ -143845,7 +144005,7 @@ const VolumeLayer = class extends CompositeLayer {
143845
144005
  signal
143846
144006
  })
143847
144007
  );
143848
- const physicalSizeScalingMatrix = getPhysicalSizeScalingMatrix(
144008
+ const physicalSizeScalingMatrix = getPhysicalSizeScalingMatrix$1(
143849
144009
  loader[resolution]
143850
144010
  );
143851
144011
  Promise.all(volumePromises).then((volumes) => {
@@ -143919,7 +144079,7 @@ const VolumeLayer = class extends CompositeLayer {
143919
144079
  };
143920
144080
  VolumeLayer.layerName = "VolumeLayer";
143921
144081
  VolumeLayer.defaultProps = defaultProps$9;
143922
- const vs = `
144082
+ const vs$1 = `
143923
144083
  #define SHADER_NAME bitmask-layer-vertex-shader
143924
144084
 
143925
144085
  attribute vec2 texCoords;
@@ -143940,7 +144100,7 @@ void main(void) {
143940
144100
  DECKGL_FILTER_COLOR(color, geometry);
143941
144101
  }
143942
144102
  `;
143943
- const fs = `
144103
+ const fs$1 = `
143944
144104
  #define SHADER_NAME bitmask-layer-fragment-shader
143945
144105
  precision highp float;
143946
144106
 
@@ -144008,14 +144168,14 @@ void main() {
144008
144168
  DECKGL_FILTER_COLOR(gl_FragColor, geometry);
144009
144169
  }
144010
144170
  `;
144011
- function padWithDefault(arr, defaultValue2, padWidth) {
144171
+ function padWithDefault$1(arr, defaultValue2, padWidth) {
144012
144172
  const newArr = [...arr];
144013
144173
  for (let i2 = 0; i2 < padWidth; i2 += 1) {
144014
144174
  newArr.push(defaultValue2);
144015
144175
  }
144016
144176
  return newArr;
144017
144177
  }
144018
- const defaultProps = {
144178
+ const defaultProps$1 = {
144019
144179
  hoveredCell: { type: "number", value: null, compare: true },
144020
144180
  // We do not want to deep-compare cellColorData,
144021
144181
  // as it is potentially a TypedArray with millions of elements.
@@ -144027,13 +144187,13 @@ const defaultProps = {
144027
144187
  // Same as with cellColorData, we do not want to deep-compare expressionData.
144028
144188
  expressionData: { type: "object", value: null, compare: 0 }
144029
144189
  };
144030
- class BitmaskLayer extends XRLayer {
144190
+ let BitmaskLayer$1 = class BitmaskLayer extends XRLayer {
144031
144191
  // eslint-disable-next-line class-methods-use-this
144032
144192
  getShaders() {
144033
144193
  const { colormap } = this.props;
144034
144194
  return {
144035
- fs,
144036
- vs,
144195
+ fs: fs$1,
144196
+ vs: vs$1,
144037
144197
  modules: [project32, picking],
144038
144198
  defines: {
144039
144199
  [COLORMAP_SHADER_PLACEHOLDER]: GLSL_COLORMAPS.includes(colormap) ? colormap : GLSL_COLORMAP_DEFAULT
@@ -144093,7 +144253,7 @@ class BitmaskLayer extends XRLayer {
144093
144253
  expressionTex,
144094
144254
  colorTexHeight: colorTex.height,
144095
144255
  colorTexWidth: colorTex.width,
144096
- channelsVisible: padWithDefault(
144256
+ channelsVisible: padWithDefault$1(
144097
144257
  channelsVisible,
144098
144258
  false,
144099
144259
  // There are six texture entries on the shaders
@@ -144130,28 +144290,632 @@ class BitmaskLayer extends XRLayer {
144130
144290
  type: GL$1.FLOAT
144131
144291
  });
144132
144292
  }
144293
+ };
144294
+ BitmaskLayer$1.layerName = "BitmaskLayer";
144295
+ BitmaskLayer$1.defaultProps = defaultProps$1;
144296
+ const vs = `
144297
+ #define SHADER_NAME bitmask-layer-vertex-shader
144298
+
144299
+ attribute vec2 texCoords;
144300
+ attribute vec3 positions;
144301
+ attribute vec3 positions64Low;
144302
+ attribute vec3 instancePickingColors;
144303
+
144304
+ varying vec2 vTexCoord;
144305
+
144306
+ void main(void) {
144307
+ geometry.worldPosition = positions;
144308
+ geometry.uv = texCoords;
144309
+ geometry.pickingColor = instancePickingColors;
144310
+ gl_Position = project_position_to_clipspace(positions, positions64Low, vec3(0.0), geometry.position);
144311
+ DECKGL_FILTER_GL_POSITION(gl_Position, geometry);
144312
+ vTexCoord = texCoords;
144313
+ vec4 color = vec4(0.0);
144314
+ DECKGL_FILTER_COLOR(color, geometry);
144315
+ }
144316
+ `;
144317
+ const fs = `
144318
+ #define SHADER_NAME bitmask-layer-fragment-shader
144319
+ precision highp float;
144320
+
144321
+ ${colormaps}
144322
+
144323
+ // Note: can have a maximum of 16 textures in most browsers
144324
+ // Reference: https://webglreport.com/
144325
+
144326
+ // Data (mask) texture
144327
+ uniform sampler2D channel0;
144328
+ uniform sampler2D channel1;
144329
+ uniform sampler2D channel2;
144330
+ uniform sampler2D channel3;
144331
+ uniform sampler2D channel4;
144332
+ uniform sampler2D channel5;
144333
+ uniform sampler2D channel6;
144334
+
144335
+ // Color texture
144336
+ uniform float hovered;
144337
+
144338
+ // Channel-specific properties
144339
+ uniform bool channelsVisible[7];
144340
+ uniform float channelOpacities[7];
144341
+ uniform bool channelIsStaticColorMode[7]; // TODO: should this be a single float?
144342
+ uniform bool channelIsSetColorMode[7]; // TODO: should this be a single float?
144343
+
144344
+ // TODO: can array of tuples/vec2 be used?
144345
+ uniform float channelColormapRangeStarts[7];
144346
+ uniform float channelColormapRangeEnds[7];
144347
+
144348
+ uniform float multiFeatureTexSize;
144349
+
144350
+ // Use one expressionTex for all channels, using an offset mechanism.
144351
+ uniform sampler2D valueTex;
144352
+ uniform float valueTexOffsets[7];
144353
+ uniform float valueTexHeight;
144354
+
144355
+ // Textures for set colors, using the same offset mechanism.
144356
+ uniform sampler2D colorTex;
144357
+ uniform float colorTexOffsets[7];
144358
+ uniform float colorTexHeight;
144359
+
144360
+
144361
+ // Static colors
144362
+ // TODO: For some reason I cannot use uniform vec3 colors[7]; and i cannot figure out why.
144363
+ uniform vec3 color0;
144364
+ uniform vec3 color1;
144365
+ uniform vec3 color2;
144366
+ uniform vec3 color3;
144367
+ uniform vec3 color4;
144368
+ uniform vec3 color5;
144369
+ uniform vec3 color6;
144370
+
144371
+ // Info for edge-only mode
144372
+ uniform float scaleFactor;
144373
+ uniform bool channelsFilled[7];
144374
+ uniform float channelStrokeWidths[7];
144375
+
144376
+ // opacity
144377
+ uniform float opacity;
144378
+
144379
+ varying vec2 vTexCoord;
144380
+
144381
+ vec3 sampleAndGetData(sampler2D dataTex, vec2 coord, bool isFilled, float strokeWidth, bool isOn) {
144382
+ float sampledData = texture(dataTex, coord).r;
144383
+ float clampedSampledData = max(0., min(sampledData, 1.));
144384
+
144385
+ bool isEdge = true;
144386
+
144387
+ if(!isFilled) {
144388
+ vec2 uTextureSize = vec2(2048.0, 2048.0);
144389
+ vec2 onePixel = vec2(1.0, 1.0) / uTextureSize;
144390
+
144391
+ // Vary the edgeSize based on user-defined stroke width.
144392
+ float edgeSize = 150.0 * strokeWidth * scaleFactor;
144393
+
144394
+ float pixN = texture(dataTex, coord + vec2(0.0, onePixel.y * edgeSize)).r;
144395
+ float pixS = texture(dataTex, coord - vec2(0.0, onePixel.y * edgeSize)).r;
144396
+ float pixW = texture(dataTex, coord + vec2(onePixel.x * edgeSize, 0.0)).r;
144397
+ float pixE = texture(dataTex, coord - vec2(onePixel.x * edgeSize, 0.0)).r;
144398
+
144399
+ float pixNW = texture(dataTex, coord + vec2(onePixel.y * edgeSize, onePixel.y * edgeSize)).r;
144400
+ float pixNE = texture(dataTex, coord + vec2(-1.0 * onePixel.x * edgeSize, onePixel.y * edgeSize)).r;
144401
+ float pixSW = texture(dataTex, coord - vec2(onePixel.x * edgeSize, onePixel.y * edgeSize)).r;
144402
+ float pixSE = texture(dataTex, coord - vec2(-1.0 * onePixel.x * edgeSize, onePixel.y * edgeSize)).r;
144403
+
144404
+ isEdge = (pixN != sampledData || pixS != sampledData || pixW != sampledData || pixE != sampledData || pixNW != sampledData || pixNE != sampledData || pixSW != sampledData || pixSE != sampledData);
144405
+ }
144406
+ // Return a tuple of (sampledData, isEdge)
144407
+ return vec3(clampedSampledData * float(isOn), sampledData, float(isEdge));
144408
+ }
144409
+
144410
+ vec4 dataToColor(vec3 sampledDataAndIsEdge, bool isStaticColorMode, vec3 channelColor, float channelOpacity, float valueOffset, float rangeStart, float rangeEnd, bool isSetColorMode, float setColorOffset) {
144411
+ float clampedSampledDataAndIsOn = sampledDataAndIsEdge.x;
144412
+ float sampledData = sampledDataAndIsEdge.y;
144413
+ float isEdge = sampledDataAndIsEdge.z;
144414
+
144415
+
144416
+ vec4 hoveredColor = float(sampledData == hovered && sampledData > 0. && hovered > 0.) * vec4(0., 0., 1., 1.);
144417
+
144418
+ // 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,
144419
+ // 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).
144420
+ float offsetSampledData = sampledData + valueOffset - 1.0;
144421
+ vec2 colorTexCoord = vec2(mod(offsetSampledData, multiFeatureTexSize) / multiFeatureTexSize, floor(offsetSampledData / multiFeatureTexSize) / (valueTexHeight - 1.));
144422
+
144423
+ // Get expression value
144424
+ float expressionValue = texture(valueTex, colorTexCoord).r / 255.;
144425
+ float scaledExpressionValue = (expressionValue - rangeStart) / max(0.005, (rangeEnd - rangeStart));
144426
+
144427
+
144428
+ // Get set color index value
144429
+ vec2 setIndicesTexCoord = vec2(mod(offsetSampledData, multiFeatureTexSize) / multiFeatureTexSize, floor(offsetSampledData / multiFeatureTexSize) / (valueTexHeight - 1.));
144430
+ float setColorIndex = texture(valueTex, setIndicesTexCoord).r;
144431
+
144432
+ // Initialize to the default "null" color.
144433
+ vec3 setColor = vec3(200. / 255., 200. / 255., 200. / 255.);
144434
+ if(setColorIndex != 0.) {
144435
+ // Subtract one from setColorIndex because we have already checked for the "null" value.
144436
+ setColorIndex = setColorIndex - 1.;
144437
+
144438
+ float setColorOffsetR = (setColorIndex + setColorOffset) * 3.0 + 0.0;
144439
+ vec2 setColorTexCoordR = vec2(mod(setColorOffsetR, multiFeatureTexSize) / multiFeatureTexSize, floor(setColorOffsetR / multiFeatureTexSize) / (colorTexHeight - 1.));
144440
+ float setColorR = texture(colorTex, setColorTexCoordR).r / 255.;
144441
+
144442
+ float setColorOffsetG = (setColorIndex + setColorOffset) * 3.0 + 1.0;
144443
+ vec2 setColorTexCoordG = vec2(mod(setColorOffsetG, multiFeatureTexSize) / multiFeatureTexSize, floor(setColorOffsetG / multiFeatureTexSize) / (colorTexHeight - 1.));
144444
+ float setColorG = texture(colorTex, setColorTexCoordG).r / 255.;
144445
+
144446
+ float setColorOffsetB = (setColorIndex + setColorOffset) * 3.0 + 2.0;
144447
+ vec2 setColorTexCoordB = vec2(mod(setColorOffsetB, multiFeatureTexSize) / multiFeatureTexSize, floor(setColorOffsetB / multiFeatureTexSize) / (colorTexHeight - 1.));
144448
+ float setColorB = texture(colorTex, setColorTexCoordB).r / 255.;
144449
+
144450
+ setColor = vec3(setColorR, setColorG, setColorB);
144451
+ }
144452
+
144453
+
144454
+ 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);
144455
+ // Only return a color if the data is non-zero.
144456
+
144457
+ return clampedSampledDataAndIsOn * isEdge * sampledColor;
144458
+ }
144459
+
144460
+ void main() {
144461
+
144462
+ // Get the color and alpha value for each channel.
144463
+ vec3 dat0 = sampleAndGetData(channel0, vTexCoord, channelsFilled[0], channelStrokeWidths[0], channelsVisible[0]);
144464
+ vec3 dat1 = sampleAndGetData(channel1, vTexCoord, channelsFilled[1], channelStrokeWidths[1], channelsVisible[1]);
144465
+ vec3 dat2 = sampleAndGetData(channel2, vTexCoord, channelsFilled[2], channelStrokeWidths[2], channelsVisible[2]);
144466
+ vec3 dat3 = sampleAndGetData(channel3, vTexCoord, channelsFilled[3], channelStrokeWidths[3], channelsVisible[3]);
144467
+ vec3 dat4 = sampleAndGetData(channel4, vTexCoord, channelsFilled[4], channelStrokeWidths[4], channelsVisible[4]);
144468
+ vec3 dat5 = sampleAndGetData(channel5, vTexCoord, channelsFilled[5], channelStrokeWidths[5], channelsVisible[5]);
144469
+ vec3 dat6 = sampleAndGetData(channel6, vTexCoord, channelsFilled[6], channelStrokeWidths[6], channelsVisible[6]);
144470
+
144471
+ vec4 val0 = dataToColor(dat0, channelIsStaticColorMode[0], color0, channelOpacities[0], valueTexOffsets[0], channelColormapRangeStarts[0], channelColormapRangeEnds[0], channelIsSetColorMode[0], colorTexOffsets[0]);
144472
+ vec4 val1 = dataToColor(dat1, channelIsStaticColorMode[1], color1, channelOpacities[1], valueTexOffsets[1], channelColormapRangeStarts[1], channelColormapRangeEnds[1], channelIsSetColorMode[1], colorTexOffsets[1]);
144473
+ vec4 val2 = dataToColor(dat2, channelIsStaticColorMode[2], color2, channelOpacities[2], valueTexOffsets[2], channelColormapRangeStarts[2], channelColormapRangeEnds[2], channelIsSetColorMode[2], colorTexOffsets[2]);
144474
+ vec4 val3 = dataToColor(dat3, channelIsStaticColorMode[3], color3, channelOpacities[3], valueTexOffsets[3], channelColormapRangeStarts[3], channelColormapRangeEnds[3], channelIsSetColorMode[3], colorTexOffsets[3]);
144475
+ vec4 val4 = dataToColor(dat4, channelIsStaticColorMode[4], color4, channelOpacities[4], valueTexOffsets[4], channelColormapRangeStarts[4], channelColormapRangeEnds[4], channelIsSetColorMode[4], colorTexOffsets[4]);
144476
+ vec4 val5 = dataToColor(dat5, channelIsStaticColorMode[5], color5, channelOpacities[5], valueTexOffsets[5], channelColormapRangeStarts[5], channelColormapRangeEnds[5], channelIsSetColorMode[5], colorTexOffsets[5]);
144477
+ vec4 val6 = dataToColor(dat6, channelIsStaticColorMode[6], color6, channelOpacities[6], valueTexOffsets[6], channelColormapRangeStarts[6], channelColormapRangeEnds[6], channelIsSetColorMode[6], colorTexOffsets[6]);
144478
+
144479
+ // If all of the channels are "empty", then discard this pixel so that it is not considered during picking.
144480
+ float emptyDat = 0.;
144481
+ if(dat0.x == emptyDat && dat1.x == emptyDat && dat2.x == emptyDat && dat3.x == emptyDat && dat4.x == emptyDat && dat5.x == emptyDat && dat6.x == emptyDat) {
144482
+ discard;
144483
+ }
144484
+
144485
+ // If the next channel color and the currently stored color (gl_FragColor) are identical,
144486
+ // or the next channel color is transparent black,
144487
+ // just use the currently stored color. Repeat this for all channels.
144488
+
144489
+ // Mix colors where necessary, using the alpha value of the next channel as the weight.
144490
+ // Use the maximum alpha value as the resulting alpha value.
144491
+ gl_FragColor = val0;
144492
+ gl_FragColor = (val1 == gl_FragColor || val1 == vec4(0.)) ? gl_FragColor : vec4(mix(gl_FragColor, val1, val1.a).rgb, max(gl_FragColor.a, val1.a));
144493
+ gl_FragColor = (val2 == gl_FragColor || val2 == vec4(0.)) ? gl_FragColor : vec4(mix(gl_FragColor, val2, val2.a).rgb, max(gl_FragColor.a, val2.a));
144494
+ gl_FragColor = (val3 == gl_FragColor || val3 == vec4(0.)) ? gl_FragColor : vec4(mix(gl_FragColor, val3, val3.a).rgb, max(gl_FragColor.a, val3.a));
144495
+ gl_FragColor = (val4 == gl_FragColor || val4 == vec4(0.)) ? gl_FragColor : vec4(mix(gl_FragColor, val4, val4.a).rgb, max(gl_FragColor.a, val4.a));
144496
+ gl_FragColor = (val5 == gl_FragColor || val5 == vec4(0.)) ? gl_FragColor : vec4(mix(gl_FragColor, val5, val5.a).rgb, max(gl_FragColor.a, val5.a));
144497
+ gl_FragColor = (val6 == gl_FragColor || val6 == vec4(0.)) ? gl_FragColor : vec4(mix(gl_FragColor, val6, val6.a).rgb, max(gl_FragColor.a, val6.a));
144498
+
144499
+
144500
+
144501
+ // TODO: multiply the resulting channel-level opacity value by the layer-level opacity value.
144502
+
144503
+ geometry.uv = vTexCoord;
144504
+ DECKGL_FILTER_COLOR(gl_FragColor, geometry);
144505
+ }
144506
+ `;
144507
+ function extent(values, valueof) {
144508
+ let min2;
144509
+ let max2;
144510
+ if (valueof === void 0) {
144511
+ for (const value of values) {
144512
+ if (value != null) {
144513
+ if (min2 === void 0) {
144514
+ if (value >= value)
144515
+ min2 = max2 = value;
144516
+ } else {
144517
+ if (min2 > value)
144518
+ min2 = value;
144519
+ if (max2 < value)
144520
+ max2 = value;
144521
+ }
144522
+ }
144523
+ }
144524
+ } else {
144525
+ let index2 = -1;
144526
+ for (let value of values) {
144527
+ if ((value = valueof(value, ++index2, values)) != null) {
144528
+ if (min2 === void 0) {
144529
+ if (value >= value)
144530
+ min2 = max2 = value;
144531
+ } else {
144532
+ if (min2 > value)
144533
+ min2 = value;
144534
+ if (max2 < value)
144535
+ max2 = value;
144536
+ }
144537
+ }
144538
+ }
144539
+ }
144540
+ return [min2, max2];
144541
+ }
144542
+ function normalize(arr) {
144543
+ const [min2, max2] = extent(arr);
144544
+ const ratio = 255 / (max2 - min2);
144545
+ const data = new Uint8Array(arr.map((i2) => Math.floor((i2 - min2) * ratio)));
144546
+ return data;
144547
+ }
144548
+ function multiSetsToTextureData(multiFeatureValues, setColorValues, channelIsSetColorMode, texSize) {
144549
+ let totalValuesLength = 0;
144550
+ let totalColorsLength = 0;
144551
+ channelIsSetColorMode.forEach((isSetColorMode, channelIndex) => {
144552
+ var _a2, _b, _c, _d, _e;
144553
+ if (isSetColorMode) {
144554
+ totalValuesLength += ((_b = (_a2 = setColorValues[channelIndex]) == null ? void 0 : _a2.obsIndex) == null ? void 0 : _b.length) || 0;
144555
+ totalColorsLength += (((_d = (_c = setColorValues[channelIndex]) == null ? void 0 : _c.setColors) == null ? void 0 : _d.length) || 0) * 3;
144556
+ } else {
144557
+ totalValuesLength += ((_e = multiFeatureValues[channelIndex]) == null ? void 0 : _e.length) || 0;
144558
+ }
144559
+ });
144560
+ const valueTexHeight = Math.max(2, Math.ceil(totalValuesLength / texSize));
144561
+ const colorTexHeight = Math.max(2, Math.ceil(totalColorsLength / texSize));
144562
+ if (valueTexHeight > texSize) {
144563
+ console.error("Error: length of concatenated quantitative feature values larger than maximum texture size");
144564
+ }
144565
+ if (colorTexHeight > texSize) {
144566
+ console.error("Error: length of concatenated quantitative feature values larger than maximum texture size");
144567
+ }
144568
+ const totalData = new Uint8Array(texSize * valueTexHeight);
144569
+ const totalColors = new Uint8Array(texSize * colorTexHeight);
144570
+ const indicesOffsets = [];
144571
+ const colorsOffsets = [];
144572
+ let indexOffset = 0;
144573
+ let colorOffset = 0;
144574
+ channelIsSetColorMode.forEach((isSetColorMode, channelIndex) => {
144575
+ if (isSetColorMode) {
144576
+ const { setColorIndices, setColors, obsIndex } = setColorValues[channelIndex] || {};
144577
+ if (setColorIndices && setColors && obsIndex) {
144578
+ for (let i2 = 0; i2 < obsIndex.length; i2++) {
144579
+ const colorIndex = setColorIndices.get(String(i2 + 1));
144580
+ totalData[indexOffset + i2] = colorIndex === void 0 ? 0 : colorIndex + 1;
144581
+ }
144582
+ for (let i2 = 0; i2 < setColors.length; i2++) {
144583
+ const { color: [r2, g2, b] } = setColors[i2];
144584
+ totalColors[(colorOffset + i2) * 3 + 0] = r2;
144585
+ totalColors[(colorOffset + i2) * 3 + 1] = g2;
144586
+ totalColors[(colorOffset + i2) * 3 + 2] = b;
144587
+ }
144588
+ }
144589
+ indicesOffsets.push(indexOffset);
144590
+ colorsOffsets.push(colorOffset);
144591
+ indexOffset += (obsIndex == null ? void 0 : obsIndex.length) || 0;
144592
+ colorOffset += (setColors == null ? void 0 : setColors.length) || 0;
144593
+ } else {
144594
+ const featureArr = multiFeatureValues[channelIndex];
144595
+ totalData.set(normalize(featureArr), indexOffset);
144596
+ indicesOffsets.push(indexOffset);
144597
+ indexOffset += featureArr.length;
144598
+ colorsOffsets.push(colorOffset);
144599
+ }
144600
+ });
144601
+ return [
144602
+ totalData,
144603
+ valueTexHeight,
144604
+ indicesOffsets,
144605
+ totalColors,
144606
+ colorTexHeight,
144607
+ colorsOffsets
144608
+ ];
144609
+ }
144610
+ const MAX_CHANNELS = 7;
144611
+ const MULTI_FEATURE_TEX_SIZE = 2048;
144612
+ function padWithDefault(arr, defaultValue2, padWidth) {
144613
+ const newArr = [...arr];
144614
+ for (let i2 = 0; i2 < padWidth; i2 += 1) {
144615
+ newArr.push(defaultValue2);
144616
+ }
144617
+ return newArr;
144618
+ }
144619
+ function getColor(arr) {
144620
+ return arr ? arr.map((v) => v / 255) : [0, 0, 0];
144621
+ }
144622
+ const defaultProps = {
144623
+ channelStrokeWidths: { type: "array", value: null, compare: true },
144624
+ channelsFilled: { type: "array", value: null, compare: true },
144625
+ channelOpacities: { type: "array", value: null, compare: true },
144626
+ channelColors: { type: "array", value: null, compare: true },
144627
+ hoveredCell: { type: "number", value: null, compare: true },
144628
+ colormap: { type: "string", value: GLSL_COLORMAP_DEFAULT, compare: true },
144629
+ expressionData: { type: "object", value: null, compare: true },
144630
+ multiFeatureValues: { type: "array", value: null, compare: true },
144631
+ setColorValues: { type: "array", value: null, compare: true },
144632
+ channelFeatureValueColormaps: { type: "array", value: null, compare: true },
144633
+ channelFeatureValueColormapRanges: { type: "array", value: null, compare: true },
144634
+ channelIsStaticColorMode: { type: "array", value: null, compare: true },
144635
+ channelIsSetColorMode: { type: "array", value: null, compare: true }
144636
+ };
144637
+ class BitmaskLayer2 extends XRLayer {
144638
+ // eslint-disable-next-line class-methods-use-this
144639
+ getShaders() {
144640
+ const { colormap } = this.props;
144641
+ return {
144642
+ fs,
144643
+ vs,
144644
+ modules: [project32, picking],
144645
+ defines: {
144646
+ [COLORMAP_SHADER_PLACEHOLDER]: GLSL_COLORMAPS.includes(colormap) ? colormap : GLSL_COLORMAP_DEFAULT
144647
+ }
144648
+ };
144649
+ }
144650
+ /**
144651
+ * Override the parent loadChannelTextures to enable
144652
+ * up to eight channels (rather than six).
144653
+ * Reference: https://github.com/hms-dbmi/viv/blob/v0.13.3/packages/layers/src/xr-layer/xr-layer.js#L316
144654
+ */
144655
+ loadChannelTextures(channelData) {
144656
+ const textures = {
144657
+ channel0: null,
144658
+ channel1: null,
144659
+ channel2: null,
144660
+ channel3: null,
144661
+ channel4: null,
144662
+ channel5: null,
144663
+ channel6: null
144664
+ };
144665
+ if (this.state.textures) {
144666
+ Object.values(this.state.textures).forEach((tex) => tex && tex.delete());
144667
+ }
144668
+ if (channelData && Object.keys(channelData).length > 0 && channelData.data) {
144669
+ channelData.data.forEach((d, i2) => {
144670
+ textures[`channel${i2}`] = this.dataToTexture(d, channelData.width, channelData.height);
144671
+ }, this);
144672
+ this.setState({ textures });
144673
+ }
144674
+ }
144675
+ updateState({ props: props2, oldProps, changeFlags }) {
144676
+ super.updateState({ props: props2, oldProps, changeFlags });
144677
+ if (props2.multiFeatureValues !== oldProps.multiFeatureValues || props2.setColorValues !== oldProps.setColorValues || props2.channelIsSetColorMode !== oldProps.channelIsSetColorMode) {
144678
+ const { multiFeatureValues, setColorValues, channelIsSetColorMode } = this.props;
144679
+ const [valueTex, colorTex, valueTexOffsets, colorTexOffsets, valueTexHeight, colorTexHeight] = this.multiSetsToTexture(multiFeatureValues, setColorValues, channelIsSetColorMode);
144680
+ this.setState({
144681
+ valueTex,
144682
+ colorTex,
144683
+ valueTexOffsets,
144684
+ colorTexOffsets,
144685
+ valueTexHeight,
144686
+ colorTexHeight
144687
+ });
144688
+ }
144689
+ if (props2.colormap !== oldProps.colormap) {
144690
+ const { gl } = this.context;
144691
+ if (this.state.model) {
144692
+ this.state.model.delete();
144693
+ }
144694
+ this.setState({ model: this._getModel(gl) });
144695
+ this.getAttributeManager().invalidateAll();
144696
+ }
144697
+ }
144698
+ draw(opts2) {
144699
+ const { uniforms } = opts2;
144700
+ const {
144701
+ channelStrokeWidths,
144702
+ channelsFilled,
144703
+ channelOpacities,
144704
+ channelColors,
144705
+ channelsVisible,
144706
+ // TODO: use `channelFeatureValueColormaps` in shader,
144707
+ // figure out how to call multiple GLSL colormap functions
144708
+ channelFeatureValueColormaps,
144709
+ channelFeatureValueColormapRanges,
144710
+ channelIsStaticColorMode,
144711
+ channelIsSetColorMode,
144712
+ hoveredCell,
144713
+ colorScaleLo,
144714
+ colorScaleHi,
144715
+ isExpressionMode,
144716
+ zoom,
144717
+ minZoom,
144718
+ maxZoom,
144719
+ zoomOffset
144720
+ // TODO: figure out if this needs to be used or not
144721
+ } = this.props;
144722
+ const {
144723
+ textures,
144724
+ model,
144725
+ // Expression and set index (and colors) textures with offsets
144726
+ valueTex,
144727
+ colorTex,
144728
+ valueTexOffsets,
144729
+ colorTexOffsets,
144730
+ valueTexHeight,
144731
+ colorTexHeight
144732
+ } = this.state;
144733
+ if (textures && model) {
144734
+ const scaleFactor = 1 / 2 ** (maxZoom - zoom);
144735
+ const colors = fromEntries(range$5(MAX_CHANNELS).map((i2) => [`color${i2}`, getColor(channelColors[i2])]));
144736
+ model.setUniforms(Object.assign({}, uniforms, {
144737
+ ...colors,
144738
+ // Bitmask image channel data textures
144739
+ ...textures,
144740
+ multiFeatureTexSize: MULTI_FEATURE_TEX_SIZE,
144741
+ // Expression textures with offsets
144742
+ valueTex,
144743
+ valueTexOffsets: padWithDefault(valueTexOffsets, 0, MAX_CHANNELS - valueTexOffsets.length),
144744
+ valueTexHeight,
144745
+ // Set indices and colors textures with offsets
144746
+ colorTex,
144747
+ colorTexOffsets: padWithDefault(colorTexOffsets, 0, MAX_CHANNELS - colorTexOffsets.length),
144748
+ colorTexHeight,
144749
+ // Visualization properties
144750
+ channelsFilled: padWithDefault(
144751
+ channelsFilled,
144752
+ true,
144753
+ // There are six texture entries on the shaders
144754
+ MAX_CHANNELS - channelsFilled.length
144755
+ ),
144756
+ channelOpacities: padWithDefault(
144757
+ channelOpacities,
144758
+ 0,
144759
+ // There are six texture entries on the shaders
144760
+ MAX_CHANNELS - channelOpacities.length
144761
+ ),
144762
+ channelStrokeWidths: padWithDefault(
144763
+ channelStrokeWidths,
144764
+ 1,
144765
+ // There are six texture entries on the shaders
144766
+ MAX_CHANNELS - channelStrokeWidths.length
144767
+ ),
144768
+ channelColormapRangeStarts: padWithDefault(
144769
+ channelFeatureValueColormapRanges.map((r2) => (r2 == null ? void 0 : r2[0]) || 0),
144770
+ 0,
144771
+ // There are six texture entries on the shaders
144772
+ MAX_CHANNELS - channelFeatureValueColormapRanges.length
144773
+ ),
144774
+ channelColormapRangeEnds: padWithDefault(
144775
+ channelFeatureValueColormapRanges.map((r2) => (r2 == null ? void 0 : r2[1]) || 1),
144776
+ 1,
144777
+ // There are six texture entries on the shaders
144778
+ MAX_CHANNELS - channelFeatureValueColormapRanges.length
144779
+ ),
144780
+ channelIsStaticColorMode: padWithDefault(
144781
+ channelIsStaticColorMode,
144782
+ true,
144783
+ // There are six texture entries on the shaders
144784
+ MAX_CHANNELS - channelIsStaticColorMode.length
144785
+ ),
144786
+ channelIsSetColorMode: padWithDefault(
144787
+ channelIsSetColorMode,
144788
+ false,
144789
+ // There are six texture entries on the shaders
144790
+ MAX_CHANNELS - channelIsSetColorMode.length
144791
+ ),
144792
+ hovered: hoveredCell || 0,
144793
+ channelsVisible: padWithDefault(
144794
+ channelsVisible,
144795
+ false,
144796
+ // There are six texture entries on the shaders
144797
+ MAX_CHANNELS - channelsVisible.length
144798
+ ),
144799
+ // uColorScaleRange: [colorScaleLo, colorScaleHi],
144800
+ // uIsExpressionMode: isExpressionMode,
144801
+ // uIsOutlined: false,
144802
+ scaleFactor
144803
+ })).draw();
144804
+ }
144805
+ }
144806
+ /**
144807
+ * This function creates textures from the data
144808
+ */
144809
+ dataToTexture(data, width, height) {
144810
+ const isWebGL2On = isWebGL2$1(this.context.gl);
144811
+ return new Texture2D(this.context.gl, {
144812
+ width,
144813
+ height,
144814
+ // Only use Float32 so we don't have to write two shaders
144815
+ data: new Float32Array(data),
144816
+ // we don't want or need mimaps
144817
+ mipmaps: false,
144818
+ parameters: {
144819
+ // NEAREST for integer data
144820
+ [GL$1.TEXTURE_MIN_FILTER]: GL$1.NEAREST,
144821
+ [GL$1.TEXTURE_MAG_FILTER]: GL$1.NEAREST,
144822
+ // CLAMP_TO_EDGE to remove tile artifacts
144823
+ [GL$1.TEXTURE_WRAP_S]: GL$1.CLAMP_TO_EDGE,
144824
+ [GL$1.TEXTURE_WRAP_T]: GL$1.CLAMP_TO_EDGE
144825
+ },
144826
+ format: isWebGL2On ? GL$1.R32F : GL$1.LUMINANCE,
144827
+ dataFormat: isWebGL2On ? GL$1.RED : GL$1.LUMINANCE,
144828
+ type: GL$1.FLOAT
144829
+ });
144830
+ }
144831
+ multiSetsToTexture(multiFeatureValues, setColorValues, channelIsSetColorMode) {
144832
+ const isWebGL2On = isWebGL2$1(this.context.gl);
144833
+ const [totalData, valueTexHeight, indicesOffsets, totalColors, colorTexHeight, colorsOffsets] = multiSetsToTextureData(multiFeatureValues, setColorValues, channelIsSetColorMode, MULTI_FEATURE_TEX_SIZE);
144834
+ return [
144835
+ // Color indices texture
144836
+ new Texture2D(this.context.gl, {
144837
+ width: MULTI_FEATURE_TEX_SIZE,
144838
+ height: valueTexHeight,
144839
+ // Only use Float32 so we don't have to write two shaders
144840
+ data: new Float32Array(totalData),
144841
+ // we don't want or need mimaps
144842
+ mipmaps: false,
144843
+ parameters: {
144844
+ // NEAREST for integer data
144845
+ [GL$1.TEXTURE_MIN_FILTER]: GL$1.NEAREST,
144846
+ [GL$1.TEXTURE_MAG_FILTER]: GL$1.NEAREST,
144847
+ // CLAMP_TO_EDGE to remove tile artifacts
144848
+ [GL$1.TEXTURE_WRAP_S]: GL$1.CLAMP_TO_EDGE,
144849
+ [GL$1.TEXTURE_WRAP_T]: GL$1.CLAMP_TO_EDGE
144850
+ },
144851
+ format: isWebGL2On ? GL$1.R32F : GL$1.LUMINANCE,
144852
+ dataFormat: isWebGL2On ? GL$1.RED : GL$1.LUMINANCE,
144853
+ type: GL$1.FLOAT
144854
+ }),
144855
+ // Colors texture
144856
+ new Texture2D(this.context.gl, {
144857
+ width: MULTI_FEATURE_TEX_SIZE,
144858
+ height: colorTexHeight,
144859
+ // Only use Float32 so we don't have to write two shaders
144860
+ data: new Float32Array(totalColors),
144861
+ // we don't want or need mimaps
144862
+ mipmaps: false,
144863
+ parameters: {
144864
+ // NEAREST for integer data
144865
+ [GL$1.TEXTURE_MIN_FILTER]: GL$1.NEAREST,
144866
+ [GL$1.TEXTURE_MAG_FILTER]: GL$1.NEAREST,
144867
+ // CLAMP_TO_EDGE to remove tile artifacts
144868
+ [GL$1.TEXTURE_WRAP_S]: GL$1.CLAMP_TO_EDGE,
144869
+ [GL$1.TEXTURE_WRAP_T]: GL$1.CLAMP_TO_EDGE
144870
+ },
144871
+ format: isWebGL2On ? GL$1.R32F : GL$1.LUMINANCE,
144872
+ dataFormat: isWebGL2On ? GL$1.RED : GL$1.LUMINANCE,
144873
+ type: GL$1.FLOAT
144874
+ }),
144875
+ // Offsets
144876
+ indicesOffsets,
144877
+ colorsOffsets,
144878
+ // Texture heights
144879
+ valueTexHeight,
144880
+ colorTexHeight
144881
+ ];
144882
+ }
144883
+ }
144884
+ BitmaskLayer2.layerName = "BitmaskLayer";
144885
+ BitmaskLayer2.defaultProps = defaultProps;
144886
+ const toRgbUIString = (on, arr, theme) => {
144887
+ const color = on || theme === "light" && (arr == null ? void 0 : arr.every((i2) => i2 === 255)) ? [220, 220, 220] : arr;
144888
+ return `rgb(${color})`;
144889
+ };
144890
+ function filterSelection(loader, selection) {
144891
+ if (!selection) {
144892
+ return selection;
144893
+ }
144894
+ const data = Array.isArray(loader) ? loader[loader.length - 1] : loader;
144895
+ const { labels } = data;
144896
+ return fromEntries(Object.entries(selection).filter(([key]) => labels.includes(key)));
144133
144897
  }
144134
- BitmaskLayer.layerName = "BitmaskLayer";
144135
- BitmaskLayer.defaultProps = defaultProps;
144136
144898
  async function getSingleSelectionStats2D({ loader, selection }) {
144137
144899
  const data = Array.isArray(loader) ? loader[loader.length - 1] : loader;
144138
- const raster = await data.getRaster({ selection });
144900
+ const filteredSelection = filterSelection(loader, selection);
144901
+ const raster = await data.getRaster({ selection: filteredSelection });
144139
144902
  const selectionStats = getChannelStats(raster.data);
144140
144903
  const { domain, contrastLimits: slider } = selectionStats;
144141
144904
  return { domain, slider };
144142
144905
  }
144143
144906
  async function getSingleSelectionStats3D({ loader, selection }) {
144144
144907
  const lowResSource = loader[loader.length - 1];
144908
+ const filteredSelection = filterSelection(lowResSource, selection);
144145
144909
  const { shape, labels } = lowResSource;
144146
144910
  const sizeZ = shape[labels.indexOf("z")] >> loader.length - 1;
144147
144911
  const raster0 = await lowResSource.getRaster({
144148
- selection: { ...selection, z: 0 }
144912
+ selection: { ...filteredSelection, z: 0 }
144149
144913
  });
144150
144914
  const rasterMid = await lowResSource.getRaster({
144151
- selection: { ...selection, z: Math.floor(sizeZ / 2) }
144915
+ selection: { ...filteredSelection, z: Math.floor(sizeZ / 2) }
144152
144916
  });
144153
144917
  const rasterTop = await lowResSource.getRaster({
144154
- selection: { ...selection, z: Math.max(0, sizeZ - 1) }
144918
+ selection: { ...filteredSelection, z: Math.max(0, sizeZ - 1) }
144155
144919
  });
144156
144920
  const stats0 = getChannelStats(raster0.data);
144157
144921
  const statsMid = getChannelStats(rasterMid.data);
@@ -144187,6 +144951,45 @@ const getMultiSelectionStats = async ({ loader, selections, use3d }) => {
144187
144951
  const sliders = stats.map((stat) => stat.slider);
144188
144952
  return { domains, sliders };
144189
144953
  };
144954
+ function getPhysicalSizeScalingMatrix(loader) {
144955
+ var _a2;
144956
+ const { x: x2, y: y2, z: z2 } = ((_a2 = loader == null ? void 0 : loader.meta) == null ? void 0 : _a2.physicalSizes) ?? {};
144957
+ if ((x2 == null ? void 0 : x2.size) && (y2 == null ? void 0 : y2.size) && (z2 == null ? void 0 : z2.size)) {
144958
+ const min2 = Math.min(z2.size, x2.size, y2.size);
144959
+ const ratio = [x2.size / min2, y2.size / min2, z2.size / min2];
144960
+ return new Matrix4().scale(ratio);
144961
+ }
144962
+ return new Matrix4().identity();
144963
+ }
144964
+ function getBoundingCube(loader) {
144965
+ const source = Array.isArray(loader) ? loader[0] : loader;
144966
+ const { shape, labels } = source;
144967
+ const physicalSizeScalingMatrix = getPhysicalSizeScalingMatrix(source);
144968
+ const xSlice = [0, physicalSizeScalingMatrix[0] * shape[labels.indexOf("x")]];
144969
+ const ySlice = [0, physicalSizeScalingMatrix[5] * shape[labels.indexOf("y")]];
144970
+ const zSlice = [
144971
+ 0,
144972
+ physicalSizeScalingMatrix[10] * shape[labels.indexOf("z")]
144973
+ ];
144974
+ return [xSlice, ySlice, zSlice];
144975
+ }
144976
+ function abbreviateNumber(value) {
144977
+ const maxLength = 5;
144978
+ let maxNaiveDigits = maxLength;
144979
+ if (!Number.isInteger(value)) {
144980
+ --maxNaiveDigits;
144981
+ }
144982
+ if (value < 1) {
144983
+ --maxNaiveDigits;
144984
+ }
144985
+ const naive = Intl.NumberFormat("en-US", {
144986
+ maximumSignificantDigits: maxNaiveDigits,
144987
+ useGrouping: false
144988
+ }).format(value);
144989
+ if (naive.length <= maxLength)
144990
+ return naive;
144991
+ return value.toExponential(0);
144992
+ }
144190
144993
  function square(x2, y2, r2) {
144191
144994
  return [[x2, y2 + r2], [x2 + r2, y2], [x2, y2 - r2], [x2 - r2, y2]];
144192
144995
  }
@@ -144226,6 +145029,35 @@ function getSourceFromLoader(loader, level) {
144226
145029
  const source = Array.isArray(data) ? data[level || data.length - 1] : data;
144227
145030
  return source;
144228
145031
  }
145032
+ const getStatsForResolution = (loader, resolution) => {
145033
+ const { shape, labels } = loader[resolution];
145034
+ const height = shape[labels.indexOf("y")];
145035
+ const width = shape[labels.indexOf("x")];
145036
+ const depth = shape[labels.indexOf("z")];
145037
+ const depthDownsampled = Math.max(1, depth >> resolution);
145038
+ const totalBytes = 4 * height * width * depthDownsampled;
145039
+ return {
145040
+ height,
145041
+ width,
145042
+ depthDownsampled,
145043
+ totalBytes
145044
+ };
145045
+ };
145046
+ const canLoadResolution = (loader, resolution) => {
145047
+ var _a2, _b, _c;
145048
+ const {
145049
+ totalBytes,
145050
+ height,
145051
+ width,
145052
+ depthDownsampled
145053
+ } = getStatsForResolution(
145054
+ loader,
145055
+ resolution
145056
+ );
145057
+ const maxHeapSize = ((_a2 = window.performance) == null ? void 0 : _a2.memory) && ((_c = (_b = window.performance) == null ? void 0 : _b.memory) == null ? void 0 : _c.jsHeapSizeLimit) / 2;
145058
+ const maxSize = maxHeapSize || 2 ** 31 - 1;
145059
+ return totalBytes < maxSize && height <= 2048 && depthDownsampled <= 2048 && width <= 2048 && depthDownsampled > 1;
145060
+ };
144229
145061
  function isRgb(loader, channels2) {
144230
145062
  const source = getSourceFromLoader(loader);
144231
145063
  const { shape, dtype, labels } = source;
@@ -144238,6 +145070,32 @@ function isRgb(loader, channels2) {
144238
145070
  }
144239
145071
  return false;
144240
145072
  }
145073
+ function physicalSizeToMatrix(xSize, ySize, zSize, xUnit, yUnit, zUnit) {
145074
+ const hasZPhyscialSize = Boolean(zSize) && Boolean(zUnit);
145075
+ const hasYPhyscialSize = Boolean(ySize) && Boolean(yUnit);
145076
+ const hasXPhyscialSize = Boolean(xSize) && Boolean(xUnit);
145077
+ if (!hasXPhyscialSize || !hasYPhyscialSize) {
145078
+ return new Matrix4().identity();
145079
+ }
145080
+ const sizes = [
145081
+ unit(`${xSize} ${xUnit}`.replace("µ", "u")),
145082
+ unit(`${ySize} ${yUnit}`.replace("µ", "u"))
145083
+ ];
145084
+ if (hasZPhyscialSize) {
145085
+ sizes.push(unit(`${zSize} ${zUnit}`.replace("µ", "u")));
145086
+ }
145087
+ const scale2 = sizes.map((i2) => divide(i2, unit("1 um")));
145088
+ if (!sizes[0].equals(sizes[1])) {
145089
+ scale2[1] = divide(sizes[1], sizes[0]);
145090
+ }
145091
+ if (!scale2[2]) {
145092
+ scale2[2] = 1;
145093
+ }
145094
+ if (isEqual$1(scale2, [1, 1, 1])) {
145095
+ return new Matrix4().identity();
145096
+ }
145097
+ return new Matrix4().scale([...scale2]);
145098
+ }
144241
145099
  function getMetaWithTransformMatrices(imageMeta, imageLoaders) {
144242
145100
  const sources = imageLoaders.map((loader) => getSourceFromLoader(loader));
144243
145101
  if (imageMeta.map((meta2) => {
@@ -144475,8 +145333,64 @@ function coordinateTransformationsToMatrix(coordinateTransformations, axes) {
144475
145333
  }
144476
145334
  return mat;
144477
145335
  }
145336
+ function hexToRgb(hex) {
145337
+ const result = /^#?([A-F\d]{2})([A-F\d]{2})([A-F\d]{2})$/i.exec(hex);
145338
+ return [
145339
+ parseInt(result[1].toLowerCase(), 16),
145340
+ parseInt(result[2].toLowerCase(), 16),
145341
+ parseInt(result[3].toLowerCase(), 16)
145342
+ ];
145343
+ }
145344
+ function normalizeCoordinateTransformations(coordinateTransformations, datasets) {
145345
+ var _a2;
145346
+ let result = [];
145347
+ if (Array.isArray(coordinateTransformations)) {
145348
+ result = coordinateTransformations.map((transform2) => {
145349
+ if (transform2.input && transform2.output) {
145350
+ const { type } = transform2;
145351
+ if (type === "translation") {
145352
+ return {
145353
+ type,
145354
+ translation: transform2.translation
145355
+ };
145356
+ }
145357
+ if (type === "scale") {
145358
+ return {
145359
+ type,
145360
+ scale: transform2.scale
145361
+ };
145362
+ }
145363
+ if (type === "identity") {
145364
+ return { type };
145365
+ }
145366
+ console.warn(`Coordinate transformation type "${type}" is not supported.`);
145367
+ }
145368
+ return transform2;
145369
+ });
145370
+ }
145371
+ if (Array.isArray((_a2 = datasets == null ? void 0 : datasets[0]) == null ? void 0 : _a2.coordinateTransformations)) {
145372
+ result = [
145373
+ ...datasets[0].coordinateTransformations,
145374
+ ...result
145375
+ ];
145376
+ }
145377
+ return result;
145378
+ }
145379
+ function getDomains() {
145380
+ const domains = {};
145381
+ const needMin = ["Int8", "Int16", "Int32"];
145382
+ Object.keys(DTYPE_VALUES).forEach((dtype) => {
145383
+ const { max: max2 } = DTYPE_VALUES[dtype];
145384
+ const min2 = needMin.includes(dtype) ? -(max2 + 1) : 0;
145385
+ domains[dtype] = [min2, max2];
145386
+ });
145387
+ return domains;
145388
+ }
145389
+ const DOMAINS = getDomains();
144478
145390
  export {
145391
+ filterSelection as A,
144479
145392
  BaseDecoder as B,
145393
+ DOMAINS as C,
144480
145394
  DEFAULT_CELLS_LAYER as D,
144481
145395
  GLOBAL_LABELS as G,
144482
145396
  DEFAULT_MOLECULES_LAYER as a,
@@ -144493,5 +145407,16 @@ export {
144493
145407
  getNgffAxes as l,
144494
145408
  getNgffAxesForTiff as m,
144495
145409
  coordinateTransformationsToMatrix as n,
144496
- square as s
145410
+ hexToRgb as o,
145411
+ physicalSizeToMatrix as p,
145412
+ getStatsForResolution as q,
145413
+ canLoadResolution as r,
145414
+ square as s,
145415
+ normalizeCoordinateTransformations as t,
145416
+ toRgbUIString as u,
145417
+ getSingleSelectionStats as v,
145418
+ getMultiSelectionStats as w,
145419
+ getPhysicalSizeScalingMatrix as x,
145420
+ getBoundingCube as y,
145421
+ abbreviateNumber as z
144497
145422
  };