@vitessce/all 3.9.4 → 3.9.6

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.
@@ -9272,6 +9272,7 @@ const FileType$1 = {
9272
9272
  // Neuroglancer
9273
9273
  // Precomputed (mesh) format
9274
9274
  OBS_SEGMENTATIONS_NG_PRECOMPUTED: "obsSegmentations.ng-precomputed",
9275
+ OBS_POINTS_NG_ANNOTATIONS: "obsPoints.ng-annotations",
9275
9276
  // New file types to support old file types:
9276
9277
  // - cells.json
9277
9278
  OBS_EMBEDDING_CELLS_JSON: "obsEmbedding.cells.json",
@@ -9478,7 +9479,7 @@ const ViewHelpMapping = {
9478
9479
  FEATURE_VALUE_HISTOGRAM: "The feature value histogram displays the distribution of values (e.g., expression) for the selected feature (e.g., gene).",
9479
9480
  DOT_PLOT: "The dot plot displays summary information about expression of the selected features (e.g., genes) for each selected observation set (e.g., cell type).",
9480
9481
  FEATURE_BAR_PLOT: "The feature bar plot displays one bar per observation (e.g., cell) along the x-axis, where the value of a selected feature (e.g., gene) is encoded along the y-axis.",
9481
- NEUROGLANCER: "The Neuroglancer view displays 3d meshes using Neuroglancer developed by Google.",
9482
+ NEUROGLANCER: "This view displays 3D meshes and points using Neuroglancer developed by Google.",
9482
9483
  TREEMAP: "The treemap provides an overview of the current state of sample-level or cell-level selection and filtering.",
9483
9484
  VOLCANO_PLOT: "The volcano plot displays differential expression results. Each data point represents a feature (as opposed to an observation).",
9484
9485
  OBS_SET_COMPOSITION_BAR_PLOT: "The set composition bar plot displays the results of a compositional analysis conducted using the scCODA method (Büttner et al. 2021 Nature Communications).",
@@ -9530,6 +9531,7 @@ const ViewHelpMapping = {
9530
9531
  [FileType$1.FEATURE_LABELS_MUDATA_ZARR]: DataType$3.FEATURE_LABELS,
9531
9532
  [FileType$1.OBS_SEGMENTATIONS_GLB]: DataType$3.OBS_SEGMENTATIONS,
9532
9533
  [FileType$1.OBS_SEGMENTATIONS_NG_PRECOMPUTED]: DataType$3.OBS_SEGMENTATIONS,
9534
+ [FileType$1.OBS_POINTS_NG_ANNOTATIONS]: DataType$3.OBS_POINTS,
9533
9535
  [FileType$1.IMAGE_SPATIALDATA_ZARR]: DataType$3.IMAGE,
9534
9536
  [FileType$1.LABELS_SPATIALDATA_ZARR]: DataType$3.OBS_SEGMENTATIONS,
9535
9537
  [FileType$1.SHAPES_SPATIALDATA_ZARR]: DataType$3.OBS_SEGMENTATIONS,
@@ -9749,6 +9751,8 @@ const ALT_ZARR_STORE_TYPES = {
9749
9751
  ];
9750
9752
  const COMPONENT_COORDINATION_TYPES = {
9751
9753
  [ViewType$1.NEUROGLANCER]: [
9754
+ CoordinationType$1.META_COORDINATION_SCOPES,
9755
+ CoordinationType$1.META_COORDINATION_SCOPES_BY,
9752
9756
  CoordinationType$1.DATASET,
9753
9757
  CoordinationType$1.SPATIAL_TARGET_X,
9754
9758
  CoordinationType$1.SPATIAL_TARGET_Y,
@@ -9770,7 +9774,26 @@ const COMPONENT_COORDINATION_TYPES = {
9770
9774
  CoordinationType$1.OBS_COLOR_ENCODING,
9771
9775
  CoordinationType$1.EMBEDDING_TYPE,
9772
9776
  CoordinationType$1.ADDITIONAL_OBS_SETS,
9773
- CoordinationType$1.TOOLTIPS_VISIBLE
9777
+ CoordinationType$1.TOOLTIPS_VISIBLE,
9778
+ CoordinationType$1.FILE_UID,
9779
+ CoordinationType$1.IMAGE_LAYER,
9780
+ CoordinationType$1.SEGMENTATION_LAYER,
9781
+ CoordinationType$1.IMAGE_CHANNEL,
9782
+ CoordinationType$1.SEGMENTATION_CHANNEL,
9783
+ CoordinationType$1.POINT_LAYER,
9784
+ CoordinationType$1.FEATURE_COLOR,
9785
+ CoordinationType$1.FEATURE_FILTER_MODE,
9786
+ CoordinationType$1.FEATURE_HIGHLIGHT,
9787
+ CoordinationType$1.FEATURE_SELECTION,
9788
+ CoordinationType$1.FEATURE_VALUE_COLORMAP,
9789
+ CoordinationType$1.FEATURE_VALUE_COLORMAP_RANGE,
9790
+ CoordinationType$1.SPATIAL_LAYER_COLOR,
9791
+ CoordinationType$1.SPATIAL_LAYER_OPACITY,
9792
+ CoordinationType$1.SPATIAL_LAYER_VISIBLE,
9793
+ CoordinationType$1.SPATIAL_CHANNEL_COLOR,
9794
+ CoordinationType$1.SPATIAL_CHANNEL_OPACITY,
9795
+ CoordinationType$1.SPATIAL_CHANNEL_VISIBLE,
9796
+ CoordinationType$1.LEGEND_VISIBLE
9774
9797
  ],
9775
9798
  [ViewType$1.SCATTERPLOT]: [
9776
9799
  CoordinationType$1.DATASET,
@@ -10877,17 +10900,26 @@ const meshGlbSchema = z.object({
10877
10900
  sceneScaleZ: z.number(),
10878
10901
  materialSide: z.enum(["front", "back"])
10879
10902
  }).partial().nullable();
10880
- const ngSchema = z.object({
10903
+ const ngPrecomputedMeshSchema = z.object({
10881
10904
  // TODO: Should this explicitly specify sharded vs. unsharded?
10882
10905
  // Or can/should that be inferred from the data?
10883
- dimensionX: z.number(),
10884
- dimensionY: z.number(),
10885
- dimensionZ: z.number(),
10886
- dimensionUnit: z.enum(["nm", "um", "µm", "mm", "cm", "m"]),
10906
+ // Note: None of these make sense to specify at the file level, since they
10907
+ // are global camera settings that would apply to all layers.
10908
+ // Intead, initial values should be set via the usual coordination space mechanism,
10909
+ // and the NeuroglancerSubscriber should handle conversion into values to pass to Neuroglancer.
10910
+ // dimensionX: z.number(),
10911
+ // dimensionY: z.number(),
10912
+ // dimensionZ: z.number(),
10913
+ // dimensionUnit: z.enum(['nm', 'um', 'µm', 'mm', 'cm', 'm']),
10887
10914
  // TODO: should the following be passed via coordination types instead?
10888
- projectionScale: z.number(),
10889
- position: z.array(z.number()).length(3),
10890
- projectionOrientation: z.array(z.number()).length(4)
10915
+ // projectionScale: z.number(),
10916
+ // position: z.array(z.number()).length(3),
10917
+ // projectionOrientation: z.array(z.number()).length(4),
10918
+ }).partial().nullable();
10919
+ const ngPointAnnotationSchema = z.object({
10920
+ projectionAnnotationSpacing: z.number(),
10921
+ featureIndexProp: z.string().optional().describe("The name of the Neuroglancer AnnotationProperty containing feature IDs. For example, specify 'gene' to use prop_gene() in the Neuroglancer shader code."),
10922
+ pointIndexProp: z.string().optional().describe("The name of the Neuroglancer AnnotationProperty containing point IDs. For example, specify 'point_id' to use prop_point_id() in the Neuroglancer shader code.")
10891
10923
  }).partial().nullable();
10892
10924
  const obsEmbeddingAnndataSchema = annDataObsEmbedding;
10893
10925
  const obsSpotsAnndataSchema = annDataObsLocations;
@@ -210319,22 +210351,22 @@ async function getDecoder(fileDirectory) {
210319
210351
  const Decoder = await importFn();
210320
210352
  return new Decoder(fileDirectory);
210321
210353
  }
210322
- addDecoder([void 0, 1], () => import("./raw-DITpx3I3.js").then((m2) => m2.default));
210323
- addDecoder(5, () => import("./lzw-D6__ol7A.js").then((m2) => m2.default));
210354
+ addDecoder([void 0, 1], () => import("./raw-B9-e46aL.js").then((m2) => m2.default));
210355
+ addDecoder(5, () => import("./lzw-DSrSjczU.js").then((m2) => m2.default));
210324
210356
  addDecoder(6, () => {
210325
210357
  throw new Error("old style JPEG compression is not supported.");
210326
210358
  });
210327
- addDecoder(7, () => import("./jpeg-GtoIw4IT.js").then((m2) => m2.default));
210328
- addDecoder([8, 32946], () => import("./deflate-ClPM2AX_.js").then((m2) => m2.default));
210329
- addDecoder(32773, () => import("./packbits-qyK2t5DY.js").then((m2) => m2.default));
210359
+ addDecoder(7, () => import("./jpeg-D6QPlXZC.js").then((m2) => m2.default));
210360
+ addDecoder([8, 32946], () => import("./deflate-BXY2A2Ns.js").then((m2) => m2.default));
210361
+ addDecoder(32773, () => import("./packbits-9-KGrvk3.js").then((m2) => m2.default));
210330
210362
  addDecoder(
210331
210363
  34887,
210332
- () => import("./lerc-DcSwwDzY.js").then(async (m2) => {
210364
+ () => import("./lerc-Cbf6R7GS.js").then(async (m2) => {
210333
210365
  await m2.zstd.init();
210334
210366
  return m2;
210335
210367
  }).then((m2) => m2.default)
210336
210368
  );
210337
- addDecoder(50001, () => import("./webimage-DggQ0O5v.js").then((m2) => m2.default));
210369
+ addDecoder(50001, () => import("./webimage-Cy-EhPIx.js").then((m2) => m2.default));
210338
210370
  function copyNewSize(array2, width2, height2, samplesPerPixel = 1) {
210339
210371
  return new (Object.getPrototypeOf(array2)).constructor(width2 * height2 * samplesPerPixel);
210340
210372
  }
@@ -227935,13 +227967,13 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
227935
227967
  */
227936
227968
  componentDidUpdate(prevProps) {
227937
227969
  this.viewInfoDidUpdate();
227938
- const shallowDiff = (propName) => prevProps[propName] !== this.props[propName];
227970
+ const shallowDiff2 = (propName) => prevProps[propName] !== this.props[propName];
227939
227971
  let forceUpdate = false;
227940
- if (["obsEmbedding", "obsEmbeddingIndex"].some(shallowDiff)) {
227972
+ if (["obsEmbedding", "obsEmbeddingIndex"].some(shallowDiff2)) {
227941
227973
  this.onUpdateCellsData();
227942
227974
  forceUpdate = true;
227943
227975
  }
227944
- if (["stratifiedData"].some(shallowDiff)) {
227976
+ if (["stratifiedData"].some(shallowDiff2)) {
227945
227977
  this.onUpdateStratifiedData();
227946
227978
  forceUpdate = true;
227947
227979
  }
@@ -227960,7 +227992,7 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
227960
227992
  "cellColorEncoding",
227961
227993
  "getExpressionValue",
227962
227994
  "embeddingPointsVisible"
227963
- ].some(shallowDiff)) {
227995
+ ].some(shallowDiff2)) {
227964
227996
  this.onUpdateCellsLayer();
227965
227997
  forceUpdate = true;
227966
227998
  }
@@ -227972,7 +228004,7 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
227972
228004
  "embeddingContoursVisible",
227973
228005
  "cellSetLabelsVisible",
227974
228006
  "cellSetLabelSize"
227975
- ].some(shallowDiff)) {
228007
+ ].some(shallowDiff2)) {
227976
228008
  this.onUpdateContourLayers();
227977
228009
  forceUpdate = true;
227978
228010
  }
@@ -227982,11 +228014,11 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
227982
228014
  "cellSetLabelsVisible",
227983
228015
  "cellSetLabelSize",
227984
228016
  "embeddingContoursVisible"
227985
- ].some(shallowDiff)) {
228017
+ ].some(shallowDiff2)) {
227986
228018
  this.onUpdateCellSetsLayers(false);
227987
228019
  forceUpdate = true;
227988
228020
  }
227989
- if (shallowDiff("viewState")) {
228021
+ if (shallowDiff2("viewState")) {
227990
228022
  this.onUpdateCellSetsLayers(true);
227991
228023
  forceUpdate = true;
227992
228024
  }
@@ -252688,21 +252720,21 @@ let Spatial$1 = class Spatial extends AbstractSpatialOrScatterplot {
252688
252720
  */
252689
252721
  componentDidUpdate(prevProps) {
252690
252722
  this.viewInfoDidUpdate();
252691
- const shallowDiff = (propName) => prevProps[propName] !== this.props[propName];
252723
+ const shallowDiff2 = (propName) => prevProps[propName] !== this.props[propName];
252692
252724
  let forceUpdate = false;
252693
252725
  if ([
252694
252726
  "obsSegmentations",
252695
252727
  "obsSegmentationsType",
252696
252728
  "obsCentroids"
252697
- ].some(shallowDiff)) {
252729
+ ].some(shallowDiff2)) {
252698
252730
  this.onUpdateCellsData();
252699
252731
  forceUpdate = true;
252700
252732
  }
252701
- if (["cellColors"].some(shallowDiff)) {
252733
+ if (["cellColors"].some(shallowDiff2)) {
252702
252734
  this.onUpdateCellColors();
252703
252735
  forceUpdate = true;
252704
252736
  }
252705
- if (["expressionData"].some(shallowDiff)) {
252737
+ if (["expressionData"].some(shallowDiff2)) {
252706
252738
  this.onUpdateExpressionData();
252707
252739
  forceUpdate = true;
252708
252740
  }
@@ -252721,7 +252753,7 @@ let Spatial$1 = class Spatial extends AbstractSpatialOrScatterplot {
252721
252753
  "cellColorEncoding",
252722
252754
  "geneExpressionColormap",
252723
252755
  "segmentationLayerCallbacks"
252724
- ].some(shallowDiff)) {
252756
+ ].some(shallowDiff2)) {
252725
252757
  this.onUpdateCellsLayer();
252726
252758
  forceUpdate = true;
252727
252759
  }
@@ -252729,7 +252761,7 @@ let Spatial$1 = class Spatial extends AbstractSpatialOrScatterplot {
252729
252761
  "obsLocations",
252730
252762
  "obsLocationsLabels",
252731
252763
  "obsLocationsFeatureIndex"
252732
- ].some(shallowDiff)) {
252764
+ ].some(shallowDiff2)) {
252733
252765
  this.onUpdateMoleculesData();
252734
252766
  forceUpdate = true;
252735
252767
  }
@@ -252739,15 +252771,15 @@ let Spatial$1 = class Spatial extends AbstractSpatialOrScatterplot {
252739
252771
  "obsLocationsIndex",
252740
252772
  "obsLocationsLabels",
252741
252773
  "obsLocationsFeatureIndex"
252742
- ].some(shallowDiff)) {
252774
+ ].some(shallowDiff2)) {
252743
252775
  this.onUpdateMoleculesLayer();
252744
252776
  forceUpdate = true;
252745
252777
  }
252746
- if (["neighborhoods"].some(shallowDiff)) {
252778
+ if (["neighborhoods"].some(shallowDiff2)) {
252747
252779
  this.onUpdateNeighborhoodsData();
252748
252780
  forceUpdate = true;
252749
252781
  }
252750
- if (["neighborhoodLayerDefsDefs", "neighborhoods"].some(shallowDiff)) {
252782
+ if (["neighborhoodLayerDefsDefs", "neighborhoods"].some(shallowDiff2)) {
252751
252783
  this.onUpdateNeighborhoodsLayer();
252752
252784
  forceUpdate = true;
252753
252785
  }
@@ -252761,7 +252793,7 @@ let Spatial$1 = class Spatial extends AbstractSpatialOrScatterplot {
252761
252793
  "imageLayerCallbacks",
252762
252794
  "geneExpressionColormap",
252763
252795
  "photometricInterpretation"
252764
- ].some(shallowDiff)) {
252796
+ ].some(shallowDiff2)) {
252765
252797
  this.onUpdateImages();
252766
252798
  forceUpdate = true;
252767
252799
  }
@@ -254511,24 +254543,24 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
254511
254543
  */
254512
254544
  componentDidUpdate(prevProps) {
254513
254545
  this.viewInfoDidUpdate();
254514
- const shallowDiff = (propName) => prevProps[propName] !== this.props[propName];
254515
- const shallowDiffByLayer = (propName, scopeName) => prevProps?.[propName]?.[scopeName] !== this.props?.[propName]?.[scopeName];
254546
+ const shallowDiff2 = (propName) => prevProps[propName] !== this.props[propName];
254547
+ const shallowDiffByLayer2 = (propName, scopeName) => prevProps?.[propName]?.[scopeName] !== this.props?.[propName]?.[scopeName];
254516
254548
  const shallowDiffByChannel = (propName, firstName, secondName) => prevProps?.[propName]?.[firstName]?.[secondName] !== this.props?.[propName]?.[firstName]?.[secondName];
254517
254549
  const shallowDiffByLayerCoordination = (propName, layerScope) => prevProps?.[propName]?.[0]?.[layerScope] !== this.props?.[propName]?.[0]?.[layerScope];
254518
254550
  const shallowDiffByChannelCoordination = (propName, layerScope, channelScope) => prevProps?.[propName]?.[0]?.[layerScope]?.[channelScope] !== this.props?.[propName]?.[0]?.[layerScope]?.[channelScope];
254519
254551
  let forceUpdate = false;
254520
- if (shallowDiff("segmentationLayerScopes")) {
254552
+ if (shallowDiff2("segmentationLayerScopes")) {
254521
254553
  this.onUpdateAllSegmentationsData();
254522
254554
  forceUpdate = true;
254523
254555
  } else {
254524
254556
  this.props.segmentationLayerScopes?.forEach((layerScope) => {
254525
- if (shallowDiffByLayer("obsSegmentations", layerScope)) {
254557
+ if (shallowDiffByLayer2("obsSegmentations", layerScope)) {
254526
254558
  this.onUpdateSegmentationsData(layerScope);
254527
254559
  forceUpdate = true;
254528
254560
  }
254529
254561
  });
254530
254562
  }
254531
- if (["segmentationLayerScopes", "segmentationChannelScopesByLayer"].some(shallowDiff)) {
254563
+ if (["segmentationLayerScopes", "segmentationChannelScopesByLayer"].some(shallowDiff2)) {
254532
254564
  this.onUpdateAllSegmentationsLocationsData();
254533
254565
  forceUpdate = true;
254534
254566
  } else {
@@ -254541,7 +254573,7 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
254541
254573
  });
254542
254574
  });
254543
254575
  }
254544
- if (["segmentationLayerScopes", "segmentationChannelScopesByLayer"].some(shallowDiff)) {
254576
+ if (["segmentationLayerScopes", "segmentationChannelScopesByLayer"].some(shallowDiff2)) {
254545
254577
  this.onUpdateAllSegmentationsSetsData();
254546
254578
  forceUpdate = true;
254547
254579
  } else {
@@ -254554,7 +254586,7 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
254554
254586
  });
254555
254587
  });
254556
254588
  }
254557
- if (["segmentationLayerScopes", "segmentationChannelScopesByLayer"].some(shallowDiff)) {
254589
+ if (["segmentationLayerScopes", "segmentationChannelScopesByLayer"].some(shallowDiff2)) {
254558
254590
  this.onUpdateAllSegmentationsIndexData();
254559
254591
  forceUpdate = true;
254560
254592
  } else {
@@ -254567,7 +254599,7 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
254567
254599
  });
254568
254600
  });
254569
254601
  }
254570
- if (["segmentationLayerScopes", "segmentationChannelScopesByLayer"].some(shallowDiff)) {
254602
+ if (["segmentationLayerScopes", "segmentationChannelScopesByLayer"].some(shallowDiff2)) {
254571
254603
  this.onUpdateAllSegmentationsExpressionData();
254572
254604
  forceUpdate = true;
254573
254605
  } else {
@@ -254592,49 +254624,49 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
254592
254624
  "segmentationLayerCoordination",
254593
254625
  "segmentationChannelScopesByLayer",
254594
254626
  "segmentationChannelCoordination"
254595
- ].some(shallowDiff)) {
254627
+ ].some(shallowDiff2)) {
254596
254628
  this.onUpdateSegmentationsLayer();
254597
254629
  forceUpdate = true;
254598
254630
  }
254599
- if (shallowDiff("spotLayerScopes")) {
254631
+ if (shallowDiff2("spotLayerScopes")) {
254600
254632
  this.onUpdateAllSpotsData();
254601
254633
  forceUpdate = true;
254602
254634
  } else {
254603
254635
  this.props.spotLayerScopes.forEach((layerScope) => {
254604
- if (shallowDiffByLayer("obsSpots", layerScope)) {
254636
+ if (shallowDiffByLayer2("obsSpots", layerScope)) {
254605
254637
  this.onUpdateSpotsData(layerScope);
254606
254638
  forceUpdate = true;
254607
254639
  }
254608
254640
  });
254609
254641
  }
254610
- if (shallowDiff("spotLayerScopes")) {
254642
+ if (shallowDiff2("spotLayerScopes")) {
254611
254643
  this.onUpdateAllSpotsSetsData();
254612
254644
  forceUpdate = true;
254613
254645
  } else {
254614
254646
  this.props.spotLayerScopes.forEach((layerScope) => {
254615
- if (shallowDiffByLayer("obsSpotsSets", layerScope) || shallowDiffByLayer("obsSpots", layerScope) || shallowDiffByLayerCoordination("spotLayerCoordination", layerScope)) {
254647
+ if (shallowDiffByLayer2("obsSpotsSets", layerScope) || shallowDiffByLayer2("obsSpots", layerScope) || shallowDiffByLayerCoordination("spotLayerCoordination", layerScope)) {
254616
254648
  this.onUpdateSpotsSetsData(layerScope);
254617
254649
  forceUpdate = true;
254618
254650
  }
254619
254651
  });
254620
254652
  }
254621
- if (shallowDiff("spotLayerScopes")) {
254653
+ if (shallowDiff2("spotLayerScopes")) {
254622
254654
  this.onUpdateAllSpotsIndexData();
254623
254655
  forceUpdate = true;
254624
254656
  } else {
254625
254657
  this.props.spotLayerScopes.forEach((layerScope) => {
254626
- if (shallowDiffByLayer("spotMatrixIndices", layerScope) || shallowDiffByLayer("obsSpots", layerScope)) {
254658
+ if (shallowDiffByLayer2("spotMatrixIndices", layerScope) || shallowDiffByLayer2("obsSpots", layerScope)) {
254627
254659
  this.onUpdateSpotsIndexData(layerScope);
254628
254660
  forceUpdate = true;
254629
254661
  }
254630
254662
  });
254631
254663
  }
254632
- if (shallowDiff("spotLayerScopes")) {
254664
+ if (shallowDiff2("spotLayerScopes")) {
254633
254665
  this.onUpdateAllSpotsExpressionData();
254634
254666
  forceUpdate = true;
254635
254667
  } else {
254636
254668
  this.props.spotLayerScopes.forEach((layerScope) => {
254637
- if (shallowDiffByLayer("spotMatrixIndices", layerScope) || shallowDiffByLayer("obsSpots", layerScope) || shallowDiffByLayer("spotMultiExpressionData", layerScope)) {
254669
+ if (shallowDiffByLayer2("spotMatrixIndices", layerScope) || shallowDiffByLayer2("obsSpots", layerScope) || shallowDiffByLayer2("spotMultiExpressionData", layerScope)) {
254638
254670
  this.onUpdateSpotsExpressionData(layerScope);
254639
254671
  forceUpdate = true;
254640
254672
  }
@@ -254649,16 +254681,16 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
254649
254681
  // Coordination props.
254650
254682
  "spotLayerScopes",
254651
254683
  "spotLayerCoordination"
254652
- ].some(shallowDiff)) {
254684
+ ].some(shallowDiff2)) {
254653
254685
  this.onUpdateSpotsLayer();
254654
254686
  forceUpdate = true;
254655
254687
  }
254656
- if (shallowDiff("pointLayerScopes")) {
254688
+ if (shallowDiff2("pointLayerScopes")) {
254657
254689
  this.onUpdateAllPointsData();
254658
254690
  forceUpdate = true;
254659
254691
  } else {
254660
254692
  this.props.pointLayerScopes.forEach((layerScope) => {
254661
- if (shallowDiffByLayer("obsPoints", layerScope) || shallowDiffByLayer("pointMultiObsLabels", layerScope) || shallowDiffByLayer("pointMatrixIndices", layerScope)) {
254693
+ if (shallowDiffByLayer2("obsPoints", layerScope) || shallowDiffByLayer2("pointMultiObsLabels", layerScope) || shallowDiffByLayer2("pointMatrixIndices", layerScope)) {
254662
254694
  this.onUpdatePointsData(layerScope);
254663
254695
  forceUpdate = true;
254664
254696
  }
@@ -254672,7 +254704,7 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
254672
254704
  // Coordination props.
254673
254705
  "pointLayerScopes",
254674
254706
  "pointLayerCoordination"
254675
- ].some(shallowDiff)) {
254707
+ ].some(shallowDiff2)) {
254676
254708
  this.onUpdatePointsLayer();
254677
254709
  forceUpdate = true;
254678
254710
  }
@@ -254684,7 +254716,7 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
254684
254716
  "imageLayerCoordination",
254685
254717
  "imageChannelScopesByLayer",
254686
254718
  "imageChannelCoordination"
254687
- ].some(shallowDiff)) {
254719
+ ].some(shallowDiff2)) {
254688
254720
  this.onUpdateImages();
254689
254721
  forceUpdate = true;
254690
254722
  }
@@ -254823,12 +254855,12 @@ class ErrorBoundary extends React__default.Component {
254823
254855
  }
254824
254856
  }
254825
254857
  const LazySpatialThree = React__default.lazy(async () => {
254826
- const { SpatialWrapper: SpatialWrapper2 } = await import("./index-5-K_2Uhu.js");
254858
+ const { SpatialWrapper: SpatialWrapper2 } = await import("./index-DKPVlERU.js");
254827
254859
  return { default: SpatialWrapper2 };
254828
254860
  });
254829
254861
  const SpatialThreeAdapter = React__default.forwardRef((props, ref2) => jsxRuntimeExports.jsx("div", { ref: ref2, style: { width: "100%", height: "100%" }, children: jsxRuntimeExports.jsx(ErrorBoundary, { children: jsxRuntimeExports.jsx(Suspense, { fallback: jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: jsxRuntimeExports.jsx(LazySpatialThree, { ...props }) }) }) }));
254830
254862
  const LazySpatialAccelerated = React__default.lazy(async () => {
254831
- const { SpatialWrapper: SpatialWrapper2 } = await import("./index-C-dFydbG.js");
254863
+ const { SpatialWrapper: SpatialWrapper2 } = await import("./index-B8V4ICbL.js");
254832
254864
  return { default: SpatialWrapper2 };
254833
254865
  });
254834
254866
  const SpatialAcceleratedAdapter = React__default.forwardRef((props, ref2) => jsxRuntimeExports.jsx("div", { ref: ref2, style: { width: "100%", height: "100%" }, children: jsxRuntimeExports.jsx(ErrorBoundary, { children: jsxRuntimeExports.jsx(Suspense, { fallback: jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: jsxRuntimeExports.jsx(LazySpatialAccelerated, { ...props }) }) }) }));
@@ -268389,7 +268421,7 @@ function HiglassGlobalStyles(props) {
268389
268421
  }
268390
268422
  register({ dataFetcher: ZarrMultivecDataFetcher_default, config: ZarrMultivecDataFetcher_default.config }, { pluginType: "dataFetcher" });
268391
268423
  const LazyHiGlassComponent = React__default.lazy(async () => {
268392
- const { HiGlassComponent } = await import("./higlass-DUYpEXhD.js");
268424
+ const { HiGlassComponent } = await import("./higlass-CQEpQgZz.js");
268393
268425
  return { default: HiGlassComponent };
268394
268426
  });
268395
268427
  const HG_SIZE = 800;
@@ -271336,7 +271368,7 @@ function NeuroglancerGlobalStyles(props) {
271336
271368
  const { classes: classes2 } = props;
271337
271369
  return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(GlobalStyles$3, { styles: globalNeuroglancerCss }), jsxRuntimeExports.jsx(ScopedGlobalStyles, { styles: globalNeuroglancerStyles, parentClassName: classes2.neuroglancerWrapper })] });
271338
271370
  }
271339
- const LazyReactNeuroglancer = React__default.lazy(() => import("./ReactNeuroglancer-BsmE8PyU.js"));
271371
+ const LazyReactNeuroglancer = React__default.lazy(() => import("./ReactNeuroglancer-Cl5UUROE.js"));
271340
271372
  function createWorker() {
271341
271373
  return new WorkerFactory();
271342
271374
  }
@@ -271413,107 +271445,548 @@ class NeuroglancerComp extends PureComponent {
271413
271445
  return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(NeuroglancerGlobalStyles, { classes: classes2 }), jsxRuntimeExports.jsx("div", { className: classes2.neuroglancerWrapper, children: jsxRuntimeExports.jsx(Suspense, { fallback: jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: jsxRuntimeExports.jsx(LazyReactNeuroglancer, { brainMapsClientId: "NOT_A_VALID_ID", viewerState, onViewerStateChanged: this.onViewerStateChanged, bundleRoot: this.bundleRoot, cellColorMapping, ref: this.onRef }) }) })] });
271414
271446
  }
271415
271447
  }
271448
+ function useMemoCustomComparison(factory2, dependencies2, customIsEqual) {
271449
+ const ref2 = useRef(
271450
+ /** @type {{ deps: any; value: T } | undefined} */
271451
+ void 0
271452
+ );
271453
+ if (ref2.current === void 0 || !customIsEqual(ref2.current.deps, dependencies2)) {
271454
+ ref2.current = { deps: dependencies2, value: factory2() };
271455
+ }
271456
+ return ref2.current.value;
271457
+ }
271458
+ const shallowDiff = (prevDeps, nextDeps, depName) => prevDeps[depName] !== nextDeps[depName];
271459
+ const shallowDiffByLayer = (prevDeps, nextDeps, depName, scopeName) => prevDeps?.[depName]?.[scopeName] !== nextDeps?.[depName]?.[scopeName];
271460
+ const shallowDiffByChannelWithKeys = (prevDeps, nextDeps, depName, firstName, secondName, keys2) => keys2.some((k) => prevDeps?.[depName]?.[firstName]?.[secondName]?.[k] !== nextDeps?.[depName]?.[firstName]?.[secondName]?.[k]);
271461
+ const shallowDiffByLayerCoordinationWithKeys = (prevDeps, nextDeps, depName, layerScope, keys2) => keys2.some((k) => prevDeps?.[depName]?.[0]?.[layerScope]?.[k] !== nextDeps?.[depName]?.[0]?.[layerScope]?.[k]);
271462
+ const shallowDiffByChannelCoordinationWithKeys = (prevDeps, nextDeps, depName, layerScope, channelScope, keys2) => keys2.some((k) => prevDeps?.[depName]?.[0]?.[layerScope]?.[channelScope]?.[k] !== nextDeps?.[depName]?.[0]?.[layerScope]?.[channelScope]?.[k]);
271463
+ function customIsEqualForCellColors(prevDeps, nextDeps) {
271464
+ let forceUpdate = false;
271465
+ const curriedShallowDiff = (depName) => shallowDiff(prevDeps, nextDeps, depName);
271466
+ const curriedShallowDiffByChannelWithKeys = (depName, firstName, secondName, keys2) => shallowDiffByChannelWithKeys(prevDeps, nextDeps, depName, firstName, secondName, keys2);
271467
+ const curriedShallowDiffByChannelCoordinationWithKeys = (depName, layerScope, channelScope, keys2) => shallowDiffByChannelCoordinationWithKeys(prevDeps, nextDeps, depName, layerScope, channelScope, keys2);
271468
+ if (curriedShallowDiff("theme")) {
271469
+ forceUpdate = true;
271470
+ }
271471
+ if (["segmentationLayerScopes", "segmentationChannelScopesByLayer"].some(curriedShallowDiff)) {
271472
+ forceUpdate = true;
271473
+ } else {
271474
+ nextDeps.segmentationLayerScopes?.forEach((layerScope) => {
271475
+ nextDeps.segmentationChannelScopesByLayer?.[layerScope]?.forEach((channelScope) => {
271476
+ if (curriedShallowDiffByChannelWithKeys("obsSegmentationsSetsData", layerScope, channelScope, [
271477
+ "obsSets",
271478
+ "obsIndex"
271479
+ ]) || curriedShallowDiffByChannelCoordinationWithKeys("segmentationChannelCoordination", layerScope, channelScope, [
271480
+ "obsSetColor",
271481
+ "obsColorEncoding",
271482
+ "obsSetSelection",
271483
+ "additionalObsSets"
271484
+ ])) {
271485
+ forceUpdate = true;
271486
+ }
271487
+ });
271488
+ });
271489
+ }
271490
+ return !forceUpdate;
271491
+ }
271492
+ function customIsEqualForInitialViewerState(prevDeps, nextDeps) {
271493
+ let forceUpdate = false;
271494
+ const curriedShallowDiff = (depName) => shallowDiff(prevDeps, nextDeps, depName);
271495
+ const curriedShallowDiffByLayer = (depName, scopeName) => shallowDiffByLayer(prevDeps, nextDeps, depName, scopeName);
271496
+ const curriedShallowDiffByLayerCoordinationWithKeys = (depName, layerScope, keys2) => shallowDiffByLayerCoordinationWithKeys(prevDeps, nextDeps, depName, layerScope, keys2);
271497
+ const curriedShallowDiffByChannelCoordinationWithKeys = (depName, layerScope, channelScope, keys2) => shallowDiffByChannelCoordinationWithKeys(prevDeps, nextDeps, depName, layerScope, channelScope, keys2);
271498
+ if (["segmentationLayerScopes", "segmentationChannelScopesByLayer"].some(curriedShallowDiff)) {
271499
+ forceUpdate = true;
271500
+ } else {
271501
+ nextDeps.segmentationLayerScopes?.forEach((layerScope) => {
271502
+ if (curriedShallowDiffByLayer("obsSegmentationsData", layerScope) || curriedShallowDiffByLayerCoordinationWithKeys("segmentationLayerCoordination", layerScope, [
271503
+ "spatialLayerVisible"
271504
+ ])) {
271505
+ forceUpdate = true;
271506
+ }
271507
+ nextDeps.segmentationChannelScopesByLayer?.[layerScope]?.forEach((channelScope) => {
271508
+ if (curriedShallowDiffByChannelCoordinationWithKeys("segmentationChannelCoordination", layerScope, channelScope, [
271509
+ "spatialChannelVisible"
271510
+ ])) {
271511
+ forceUpdate = true;
271512
+ }
271513
+ });
271514
+ });
271515
+ }
271516
+ if (curriedShallowDiff("pointLayerScopes")) {
271517
+ forceUpdate = true;
271518
+ } else {
271519
+ nextDeps.pointLayerScopes?.forEach((layerScope) => {
271520
+ if (curriedShallowDiffByLayer("obsPointsData", layerScope) || curriedShallowDiffByLayer("pointMultiIndicesData", layerScope) || curriedShallowDiffByLayerCoordinationWithKeys("pointLayerCoordination", layerScope, [
271521
+ "spatialLayerVisible",
271522
+ "obsColorEncoding",
271523
+ "spatialLayerColor",
271524
+ "featureSelection",
271525
+ "featureFilterMode",
271526
+ "featureColor"
271527
+ ]) || Math.abs(prevDeps?.pointLayerCoordination?.[0]?.[layerScope]?.spatialLayerOpacity - nextDeps?.pointLayerCoordination?.[0]?.[layerScope]?.spatialLayerOpacity) >= 0.05) {
271528
+ forceUpdate = true;
271529
+ }
271530
+ });
271531
+ }
271532
+ return !forceUpdate;
271533
+ }
271534
+ function normalizeColor(rgbColor) {
271535
+ return rgbColor.map((c2) => c2 / 255);
271536
+ }
271537
+ function toVec3(normalizedColor) {
271538
+ return `vec3(${normalizedColor.join(", ")})`;
271539
+ }
271540
+ function toVec4(normalizedColor, alpha2) {
271541
+ return `vec4(${normalizedColor.join(", ")}, ${alpha2})`;
271542
+ }
271543
+ function getSpatialLayerColorShader(staticColor, opacity2) {
271544
+ const norm2 = normalizeColor(staticColor);
271545
+ return `
271546
+ void main() {
271547
+ setColor(${toVec4(norm2, opacity2)});
271548
+ }
271549
+ `;
271550
+ }
271551
+ function getSpatialLayerColorWithSelectionShader(staticColor, opacity2, featureIndices, defaultColor, featureIndexProp) {
271552
+ const normStatic = normalizeColor(staticColor);
271553
+ const normDefault = normalizeColor(defaultColor);
271554
+ const numFeatures = featureIndices.length;
271555
+ const indicesArr = `int selectedIndices[${numFeatures}] = int[${numFeatures}](${featureIndices.join(", ")});`;
271556
+ return `
271557
+ void main() {
271558
+ int geneIndex = prop_${featureIndexProp}();
271559
+ ${indicesArr}
271560
+ bool isSelected = false;
271561
+ for (int i = 0; i < ${numFeatures}; ++i) {
271562
+ if (geneIndex == selectedIndices[i]) {
271563
+ isSelected = true;
271564
+ }
271565
+ }
271566
+ if (isSelected) {
271567
+ setColor(${toVec4(normStatic, opacity2)});
271568
+ } else {
271569
+ setColor(${toVec4(normDefault, opacity2)});
271570
+ }
271571
+ }
271572
+ `;
271573
+ }
271574
+ function getSpatialLayerColorFilteredShader(staticColor, opacity2, featureIndices, featureIndexProp) {
271575
+ const normStatic = normalizeColor(staticColor);
271576
+ const numFeatures = featureIndices.length;
271577
+ const indicesArr = `int selectedIndices[${numFeatures}] = int[${numFeatures}](${featureIndices.join(", ")});`;
271578
+ return `
271579
+ void main() {
271580
+ int geneIndex = prop_${featureIndexProp}();
271581
+ ${indicesArr}
271582
+ bool isSelected = false;
271583
+ for (int i = 0; i < ${numFeatures}; ++i) {
271584
+ if (geneIndex == selectedIndices[i]) {
271585
+ isSelected = true;
271586
+ }
271587
+ }
271588
+ if (!isSelected) {
271589
+ discard;
271590
+ }
271591
+ setColor(${toVec4(normStatic, opacity2)});
271592
+ }
271593
+ `;
271594
+ }
271595
+ function getGeneSelectionNoSelectionShader(staticColor, opacity2) {
271596
+ const norm2 = normalizeColor(staticColor);
271597
+ return `
271598
+ void main() {
271599
+ setColor(${toVec4(norm2, opacity2)});
271600
+ }
271601
+ `;
271602
+ }
271603
+ function getGeneSelectionWithSelectionShader(featureIndices, featureColors, staticColor, defaultColor, opacity2, featureIndexProp) {
271604
+ const numFeatures = featureIndices.length;
271605
+ const normDefault = normalizeColor(defaultColor);
271606
+ const normColors = featureColors.map((c2) => normalizeColor(c2));
271607
+ const normStatic = normalizeColor(staticColor);
271608
+ const colorArr = normColors.map((c2) => c2 ? toVec3(c2) : toVec3(normStatic));
271609
+ const indicesDecl = `int selectedIndices[${numFeatures}] = int[${numFeatures}](${featureIndices.join(", ")});`;
271610
+ const colorsDecl = `vec3 featureColors[${numFeatures}] = vec3[${numFeatures}](${colorArr.join(", ")});`;
271611
+ return `
271612
+ void main() {
271613
+ int geneIndex = prop_${featureIndexProp}();
271614
+ ${indicesDecl}
271615
+ ${colorsDecl}
271616
+ vec4 color = ${toVec4(normDefault, opacity2)};
271617
+ for (int i = 0; i < ${numFeatures}; ++i) {
271618
+ if (geneIndex == selectedIndices[i]) {
271619
+ color = vec4(featureColors[i], ${opacity2});
271620
+ }
271621
+ }
271622
+ setColor(color);
271623
+ }
271624
+ `;
271625
+ }
271626
+ function getGeneSelectionFilteredShader(featureIndices, featureColors, staticColor, opacity2, featureIndexProp) {
271627
+ const numFeatures = featureIndices.length;
271628
+ const normColors = featureColors.map((c2) => normalizeColor(c2));
271629
+ const normStatic = normalizeColor(staticColor);
271630
+ const colorArr = normColors.map((c2) => c2 ? toVec3(c2) : toVec3(normStatic));
271631
+ const indicesDecl = `int selectedIndices[${numFeatures}] = int[${numFeatures}](${featureIndices.join(", ")});`;
271632
+ const colorsDecl = `vec3 featureColors[${numFeatures}] = vec3[${numFeatures}](${colorArr.join(", ")});`;
271633
+ return `
271634
+ void main() {
271635
+ int geneIndex = prop_${featureIndexProp}();
271636
+ ${indicesDecl}
271637
+ ${colorsDecl}
271638
+ bool isSelected = false;
271639
+ vec3 matchedColor = vec3(0.0);
271640
+ for (int i = 0; i < ${numFeatures}; ++i) {
271641
+ if (geneIndex == selectedIndices[i]) {
271642
+ isSelected = true;
271643
+ matchedColor = featureColors[i];
271644
+ }
271645
+ }
271646
+ if (!isSelected) {
271647
+ discard;
271648
+ }
271649
+ setColor(vec4(matchedColor, ${opacity2}));
271650
+ }
271651
+ `;
271652
+ }
271653
+ function getRandomByFeatureShader(opacity2, featureIndexProp) {
271654
+ const paletteSize = PALETTE.length;
271655
+ const normPalette = PALETTE.map((c2) => normalizeColor(c2));
271656
+ const paletteDecl = `vec3 palette[${paletteSize}] = vec3[${paletteSize}](${normPalette.map((c2) => toVec3(c2)).join(", ")});`;
271657
+ return `
271658
+ void main() {
271659
+ int geneIndex = prop_${featureIndexProp}();
271660
+ ${paletteDecl}
271661
+ int colorIdx = geneIndex - (geneIndex / ${paletteSize}) * ${paletteSize};
271662
+ if (colorIdx < 0) { colorIdx = -colorIdx; }
271663
+ vec3 color = palette[colorIdx];
271664
+ setColor(vec4(color, ${opacity2}));
271665
+ }
271666
+ `;
271667
+ }
271668
+ function getRandomByFeatureWithSelectionShader(featureIndices, defaultColor, opacity2, featureIndexProp) {
271669
+ const paletteSize = PALETTE.length;
271670
+ const normPalette = PALETTE.map((c2) => normalizeColor(c2));
271671
+ const normDefault = normalizeColor(defaultColor);
271672
+ const numFeatures = featureIndices.length;
271673
+ const paletteDecl = `vec3 palette[${paletteSize}] = vec3[${paletteSize}](${normPalette.map((c2) => toVec3(c2)).join(", ")});`;
271674
+ const indicesDecl = `int selectedIndices[${numFeatures}] = int[${numFeatures}](${featureIndices.join(", ")});`;
271675
+ return `
271676
+ void main() {
271677
+ int geneIndex = prop_${featureIndexProp}();
271678
+ ${paletteDecl}
271679
+ ${indicesDecl}
271680
+ bool isSelected = false;
271681
+ for (int i = 0; i < ${numFeatures}; ++i) {
271682
+ if (geneIndex == selectedIndices[i]) {
271683
+ isSelected = true;
271684
+ }
271685
+ }
271686
+ if (isSelected) {
271687
+ int colorIdx = geneIndex - (geneIndex / ${paletteSize}) * ${paletteSize};
271688
+ if (colorIdx < 0) { colorIdx = -colorIdx; }
271689
+ setColor(vec4(palette[colorIdx], ${opacity2}));
271690
+ } else {
271691
+ setColor(${toVec4(normDefault, opacity2)});
271692
+ }
271693
+ }
271694
+ `;
271695
+ }
271696
+ function getRandomByFeatureFilteredShader(featureIndices, opacity2, featureIndexProp) {
271697
+ const paletteSize = PALETTE.length;
271698
+ const normPalette = PALETTE.map((c2) => normalizeColor(c2));
271699
+ const numFeatures = featureIndices.length;
271700
+ const paletteDecl = `vec3 palette[${paletteSize}] = vec3[${paletteSize}](${normPalette.map((c2) => toVec3(c2)).join(", ")});`;
271701
+ const indicesDecl = `int selectedIndices[${numFeatures}] = int[${numFeatures}](${featureIndices.join(", ")});`;
271702
+ return `
271703
+ void main() {
271704
+ int geneIndex = prop_${featureIndexProp}();
271705
+ ${paletteDecl}
271706
+ ${indicesDecl}
271707
+ bool isSelected = false;
271708
+ for (int i = 0; i < ${numFeatures}; ++i) {
271709
+ if (geneIndex == selectedIndices[i]) {
271710
+ isSelected = true;
271711
+ }
271712
+ }
271713
+ if (!isSelected) {
271714
+ discard;
271715
+ }
271716
+ int colorIdx = geneIndex - (geneIndex / ${paletteSize}) * ${paletteSize};
271717
+ if (colorIdx < 0) { colorIdx = -colorIdx; }
271718
+ setColor(vec4(palette[colorIdx], ${opacity2}));
271719
+ }
271720
+ `;
271721
+ }
271722
+ function hashToFloatGlsl() {
271723
+ return `
271724
+ float hashToFloat(int v, int seed) {
271725
+ int h = v ^ (seed * 16777619);
271726
+ h = h * 747796405 + 2891336453;
271727
+ h = ((h >> 16) ^ h) * 2654435769;
271728
+ h = ((h >> 16) ^ h);
271729
+ return float(h & 0x7FFFFFFF) / float(0x7FFFFFFF);
271730
+ }
271731
+ `;
271732
+ }
271733
+ function getRandomPerPointShader(opacity2, featureIndexProp, pointIndexProp) {
271734
+ return `
271735
+ ${hashToFloatGlsl()}
271736
+ void main() {
271737
+ int geneIndex = prop_${featureIndexProp}();
271738
+ int pointIndex = prop_${pointIndexProp}();
271739
+ float r = hashToFloat(pointIndex, 0);
271740
+ float g = hashToFloat(pointIndex, 1);
271741
+ float b = hashToFloat(pointIndex, 2);
271742
+ setColor(vec4(r, g, b, ${opacity2}));
271743
+ }
271744
+ `;
271745
+ }
271746
+ function getRandomPerPointWithSelectionShader(featureIndices, defaultColor, opacity2, featureIndexProp, pointIndexProp) {
271747
+ const normDefault = normalizeColor(defaultColor);
271748
+ const numFeatures = featureIndices.length;
271749
+ const indicesDecl = `int selectedIndices[${numFeatures}] = int[${numFeatures}](${featureIndices.join(", ")});`;
271750
+ return `
271751
+ ${hashToFloatGlsl()}
271752
+ void main() {
271753
+ int geneIndex = prop_${featureIndexProp}();
271754
+ int pointIndex = prop_${pointIndexProp}();
271755
+ ${indicesDecl}
271756
+ bool isSelected = false;
271757
+ for (int i = 0; i < ${numFeatures}; ++i) {
271758
+ if (geneIndex == selectedIndices[i]) {
271759
+ isSelected = true;
271760
+ }
271761
+ }
271762
+ if (isSelected) {
271763
+ float r = hashToFloat(pointIndex, 0);
271764
+ float g = hashToFloat(pointIndex, 1);
271765
+ float b = hashToFloat(pointIndex, 2);
271766
+ setColor(vec4(r, g, b, ${opacity2}));
271767
+ } else {
271768
+ setColor(${toVec4(normDefault, opacity2)});
271769
+ }
271770
+ }
271771
+ `;
271772
+ }
271773
+ function getRandomPerPointFilteredShader(featureIndices, opacity2, featureIndexProp, pointIndexProp) {
271774
+ const numFeatures = featureIndices.length;
271775
+ const indicesDecl = `int selectedIndices[${numFeatures}] = int[${numFeatures}](${featureIndices.join(", ")});`;
271776
+ return `
271777
+ ${hashToFloatGlsl()}
271778
+ void main() {
271779
+ int geneIndex = prop_${featureIndexProp}();
271780
+ int pointIndex = prop_${pointIndexProp}();
271781
+ ${indicesDecl}
271782
+ bool isSelected = false;
271783
+ for (int i = 0; i < ${numFeatures}; ++i) {
271784
+ if (geneIndex == selectedIndices[i]) {
271785
+ isSelected = true;
271786
+ }
271787
+ }
271788
+ if (!isSelected) {
271789
+ discard;
271790
+ }
271791
+ float r = hashToFloat(pointIndex, 0);
271792
+ float g = hashToFloat(pointIndex, 1);
271793
+ float b = hashToFloat(pointIndex, 2);
271794
+ setColor(vec4(r, g, b, ${opacity2}));
271795
+ }
271796
+ `;
271797
+ }
271798
+ function getPointsShader(layerCoordination) {
271799
+ const { theme, featureIndex, spatialLayerOpacity, obsColorEncoding, spatialLayerColor, featureSelection, featureFilterMode, featureColor, featureIndexProp, pointIndexProp } = layerCoordination;
271800
+ const defaultColor = getDefaultColor(theme);
271801
+ const opacity2 = spatialLayerOpacity ?? 1;
271802
+ const staticColor = Array.isArray(spatialLayerColor) && spatialLayerColor.length === 3 ? spatialLayerColor : defaultColor;
271803
+ const hasFeatureSelection = Array.isArray(featureSelection) && featureSelection.length > 0;
271804
+ const isFiltered = featureFilterMode === "featureSelection";
271805
+ let featureIndices = [];
271806
+ if (hasFeatureSelection && Array.isArray(featureIndex)) {
271807
+ featureIndices = featureSelection.map((name2) => featureIndex.indexOf(name2)).filter((i2) => i2 >= 0);
271808
+ }
271809
+ const hasResolvedIndices = featureIndices.length > 0;
271810
+ const resolvedFeatureColors = hasResolvedIndices ? featureSelection.filter((name2) => featureIndex?.indexOf(name2) >= 0).map((name2) => {
271811
+ const match2 = Array.isArray(featureColor) ? featureColor.find((fc) => fc.name === name2)?.color : null;
271812
+ return match2 || staticColor;
271813
+ }) : [];
271814
+ if (obsColorEncoding === "spatialLayerColor") {
271815
+ if (!hasFeatureSelection || !hasResolvedIndices) {
271816
+ return getSpatialLayerColorShader(staticColor, opacity2);
271817
+ }
271818
+ if (isFiltered) {
271819
+ return getSpatialLayerColorFilteredShader(staticColor, opacity2, featureIndices, featureIndexProp);
271820
+ }
271821
+ return getSpatialLayerColorWithSelectionShader(staticColor, opacity2, featureIndices, defaultColor, featureIndexProp);
271822
+ }
271823
+ if (obsColorEncoding === "geneSelection") {
271824
+ if (!featureIndexProp) {
271825
+ throw new Error("In order to use gene-based color encoding for Neuroglancer Points, options.featureIndexProp must be specified for the obsPoints.ng-annotations fileType in the Vitessce configuration.");
271826
+ }
271827
+ if (!hasFeatureSelection || !hasResolvedIndices) {
271828
+ return getGeneSelectionNoSelectionShader(staticColor, opacity2);
271829
+ }
271830
+ if (isFiltered) {
271831
+ return getGeneSelectionFilteredShader(featureIndices, resolvedFeatureColors, staticColor, opacity2, featureIndexProp);
271832
+ }
271833
+ return getGeneSelectionWithSelectionShader(featureIndices, resolvedFeatureColors, staticColor, defaultColor, opacity2, featureIndexProp);
271834
+ }
271835
+ if (obsColorEncoding === "randomByFeature") {
271836
+ if (!featureIndexProp) {
271837
+ throw new Error("In order to use gene-based color encoding for Neuroglancer Points, options.featureIndexProp must be specified for the obsPoints.ng-annotations fileType in the Vitessce configuration.");
271838
+ }
271839
+ if (!hasFeatureSelection || !hasResolvedIndices) {
271840
+ return getRandomByFeatureShader(opacity2, featureIndexProp);
271841
+ }
271842
+ if (isFiltered) {
271843
+ return getRandomByFeatureFilteredShader(featureIndices, opacity2, featureIndexProp);
271844
+ }
271845
+ return getRandomByFeatureWithSelectionShader(featureIndices, defaultColor, opacity2, featureIndexProp);
271846
+ }
271847
+ if (obsColorEncoding === "random") {
271848
+ if (!pointIndexProp) {
271849
+ throw new Error("In order to use per-point color encoding for Neuroglancer Points, options.pointIndexProp must be specified for the obsPoints.ng-annotations fileType in the Vitessce configuration.");
271850
+ }
271851
+ if (!hasFeatureSelection || !hasResolvedIndices) {
271852
+ return getRandomPerPointShader(opacity2, featureIndexProp, pointIndexProp);
271853
+ }
271854
+ if (isFiltered) {
271855
+ return getRandomPerPointFilteredShader(featureIndices, opacity2, featureIndexProp, pointIndexProp);
271856
+ }
271857
+ return getRandomPerPointWithSelectionShader(featureIndices, defaultColor, opacity2, featureIndexProp, pointIndexProp);
271858
+ }
271859
+ return getSpatialLayerColorShader(staticColor, opacity2);
271860
+ }
271416
271861
  const DEFAULT_NG_PROPS = {
271417
271862
  layout: "3d",
271418
271863
  position: [0, 0, 0],
271419
271864
  projectionOrientation: [0, 0, 0, 1],
271420
271865
  projectionScale: 1024,
271421
- crossSectionScale: 1
271866
+ crossSectionScale: 1,
271867
+ dimensions: {
271868
+ x: [1, "nm"],
271869
+ y: [1, "nm"],
271870
+ z: [1, "nm"]
271871
+ },
271872
+ layers: []
271422
271873
  };
271423
271874
  function toPrecomputedSource(url) {
271424
271875
  if (!url) {
271425
- return void 0;
271876
+ throw new Error("toPrecomputedSource: URL is required");
271426
271877
  }
271427
271878
  return `precomputed://${url}`;
271428
271879
  }
271429
- const UNIT_TO_NM = {
271430
- nm: 1,
271431
- um: 1e3,
271432
- µm: 1e3,
271433
- mm: 1e6,
271434
- cm: 1e7,
271435
- m: 1e9
271436
- };
271437
- function isInNanometerRange(value2, unit2, minNm = 1, maxNm = 100) {
271438
- const n3 = typeof value2 === "number" ? value2 : Number(value2);
271439
- if (!Number.isFinite(n3))
271440
- return false;
271441
- const factor = unit2 && UNIT_TO_NM[unit2];
271442
- if (!factor)
271443
- return false;
271444
- const nm = n3 * factor;
271445
- return nm >= minNm && nm <= maxNm;
271446
- }
271447
- function normalizeDimensionsToNanometers(opts2) {
271448
- const { dimensionUnit, dimensionX, dimensionY, dimensionZ } = opts2;
271449
- if (!dimensionUnit || !dimensionX || !dimensionY || !dimensionZ) {
271450
- console.warn("Missing dimension info");
271880
+ function toNgLayerName(dataType, layerScope, channelScope = null) {
271881
+ if (dataType === DataType$3.OBS_SEGMENTATIONS) {
271882
+ return `obsSegmentations-${layerScope}-${channelScope}`;
271451
271883
  }
271452
- const xNm = isInNanometerRange(dimensionX, dimensionUnit);
271453
- const yNm = isInNanometerRange(dimensionY, dimensionUnit);
271454
- const zNm = isInNanometerRange(dimensionZ, dimensionUnit);
271455
- if (!xNm || !yNm || !zNm) {
271456
- console.warn("Dimension was converted to nm units");
271884
+ if (dataType === DataType$3.OBS_POINTS) {
271885
+ return `obsPoints-${layerScope}`;
271457
271886
  }
271458
- return {
271459
- x: xNm ? [dimensionX, dimensionUnit] : [1, "nm"],
271460
- y: yNm ? [dimensionY, dimensionUnit] : [1, "nm"],
271461
- z: zNm ? [dimensionZ, dimensionUnit] : [1, "nm"]
271462
- };
271887
+ throw new Error(`Unsupported data type: ${dataType}`);
271463
271888
  }
271464
- function extractDataTypeEntities(loaders, dataset, dataType) {
271465
- const datasetEntry = loaders?.[dataset];
271466
- const internMap = datasetEntry?.loaders?.[dataType];
271467
- if (!internMap || typeof internMap.entries !== "function")
271468
- return [];
271469
- return Array.from(internMap.entries()).map(([key2, loader2]) => {
271470
- const url = loader2?.url ?? loader2?.dataSource?.url ?? void 0;
271471
- const fileUid = key2?.fileUid ?? loader2?.coordinationValues?.fileUid ?? void 0;
271472
- const { position: position2, projectionOrientation, projectionScale, crossSectionScale } = loader2?.options ?? {};
271473
- const isPrecomputed = loader2?.fileType.includes("precomputed");
271474
- if (!isPrecomputed) {
271475
- console.warn("Filetype needs to be precomputed");
271476
- }
271477
- return {
271478
- key: key2,
271479
- type: "segmentation",
271480
- fileUid,
271481
- layout: DEFAULT_NG_PROPS.layout,
271482
- url,
271483
- source: toPrecomputedSource(url),
271484
- name: fileUid ?? key2?.name ?? "segmentation",
271485
- // For precomputed: nm is the unit used
271486
- dimensions: normalizeDimensionsToNanometers(loader2?.options),
271487
- // If not provided, no error, but difficult to see the data
271488
- position: Array.isArray(position2) && position2.length === 3 ? position2 : DEFAULT_NG_PROPS.position,
271489
- // If not provided, will have a default orientation
271490
- projectionOrientation: Array.isArray(projectionOrientation) && projectionOrientation.length === 4 ? projectionOrientation : DEFAULT_NG_PROPS.projectionOrientation,
271491
- projectionScale: Number.isFinite(projectionScale) ? projectionScale : DEFAULT_NG_PROPS.projectionScale,
271492
- crossSectionScale: Number.isFinite(crossSectionScale) ? crossSectionScale : DEFAULT_NG_PROPS.crossSectionScale
271493
- };
271494
- });
271495
- }
271496
- function useExtractOptionsForNg(loaders, dataset, dataType) {
271497
- const extractedEntities = useMemo$1(() => extractDataTypeEntities(loaders, dataset, dataType), [loaders, dataset, dataType]);
271498
- const layers = useMemo$1(() => extractedEntities.filter((t4) => t4.source).map((t4) => ({
271499
- type: t4.type,
271500
- source: t4.source,
271501
- segments: [],
271502
- name: t4.name || "segmentation"
271503
- })), [extractedEntities]);
271504
- const viewerState = useMemo$1(() => ({
271505
- dimensions: extractedEntities[0]?.dimensions,
271506
- position: extractedEntities[0]?.position,
271507
- crossSectionScale: extractedEntities[0]?.crossSectionScale,
271508
- projectionOrientation: extractedEntities[0]?.projectionOrientation,
271509
- projectionScale: extractedEntities[0]?.projectionScale,
271510
- layers,
271511
- layout: extractedEntities[0].layout
271512
- }));
271513
- return [viewerState];
271514
- }
271515
- function useNeuroglancerViewerState(loaders, dataset, isRequired, coordinationSetters, initialCoordinationValues, matchOn) {
271516
- return useExtractOptionsForNg(loaders, dataset, DataType$3.OBS_SEGMENTATIONS);
271889
+ function useNeuroglancerViewerState(theme, segmentationLayerScopes, segmentationChannelScopesByLayer, segmentationLayerCoordination, segmentationChannelCoordination, obsSegmentationsUrls, obsSegmentationsData, pointLayerScopes, pointLayerCoordination, obsPointsUrls, obsPointsData, pointMultiIndicesData) {
271890
+ const viewerState = useMemoCustomComparison(() => {
271891
+ let result = cloneDeep$1(DEFAULT_NG_PROPS);
271892
+ segmentationLayerScopes.forEach((layerScope) => {
271893
+ const layerCoordination = segmentationLayerCoordination[0][layerScope];
271894
+ const channelScopes = segmentationChannelScopesByLayer[layerScope] || [];
271895
+ const layerData = obsSegmentationsData[layerScope];
271896
+ const layerUrl = obsSegmentationsUrls[layerScope]?.[0]?.url;
271897
+ if (layerUrl && layerData) {
271898
+ const { spatialLayerVisible } = layerCoordination || {};
271899
+ channelScopes.forEach((channelScope) => {
271900
+ const channelCoordination = segmentationChannelCoordination[0]?.[layerScope]?.[channelScope];
271901
+ const { spatialChannelVisible } = channelCoordination || {};
271902
+ result = {
271903
+ ...result,
271904
+ layers: [
271905
+ ...result.layers,
271906
+ {
271907
+ type: "segmentation",
271908
+ source: toPrecomputedSource(layerUrl),
271909
+ segments: [],
271910
+ name: toNgLayerName(DataType$3.OBS_SEGMENTATIONS, layerScope, channelScope),
271911
+ visible: spatialLayerVisible && spatialChannelVisible,
271912
+ // Both layer and channel
271913
+ // visibility must be true for the layer to be visible.
271914
+ // TODO: update this to extract specific properties from
271915
+ // neuroglancerOptions as needed.
271916
+ ...layerData.neuroglancerOptions ?? {}
271917
+ }
271918
+ ]
271919
+ };
271920
+ });
271921
+ }
271922
+ });
271923
+ pointLayerScopes.forEach((layerScope) => {
271924
+ const layerCoordination = pointLayerCoordination[0][layerScope];
271925
+ const layerData = obsPointsData[layerScope];
271926
+ const layerUrl = obsPointsUrls[layerScope]?.[0]?.url;
271927
+ const featureIndex = pointMultiIndicesData[layerScope]?.featureIndex;
271928
+ if (layerUrl && layerData) {
271929
+ const { spatialLayerVisible, spatialLayerOpacity, obsColorEncoding, spatialLayerColor, featureSelection, featureFilterMode, featureColor } = layerCoordination || {};
271930
+ const shader = getPointsShader({
271931
+ theme,
271932
+ featureIndex,
271933
+ spatialLayerOpacity,
271934
+ obsColorEncoding,
271935
+ spatialLayerColor,
271936
+ featureSelection,
271937
+ featureFilterMode,
271938
+ featureColor,
271939
+ featureIndexProp: layerData.neuroglancerOptions?.featureIndexProp,
271940
+ pointIndexProp: layerData.neuroglancerOptions?.pointIndexProp
271941
+ });
271942
+ result = {
271943
+ ...result,
271944
+ layers: [
271945
+ ...result.layers,
271946
+ {
271947
+ type: "annotation",
271948
+ source: {
271949
+ url: toPrecomputedSource(layerUrl),
271950
+ subsources: {
271951
+ default: true
271952
+ },
271953
+ enableDefaultSubsources: false
271954
+ },
271955
+ tab: "annotations",
271956
+ shader,
271957
+ name: toNgLayerName(DataType$3.OBS_POINTS, layerScope),
271958
+ visible: spatialLayerVisible,
271959
+ // Options from layerData.neuroglancerOptions
271960
+ // like projectionAnnotationSpacing:
271961
+ projectionAnnotationSpacing: layerData.neuroglancerOptions?.projectionAnnotationSpacing ?? 1
271962
+ }
271963
+ ],
271964
+ // TODO: is this needed?
271965
+ // The selected layer here will overwrite anything
271966
+ // that was previously specified.
271967
+ selectedLayer: {
271968
+ // size: ? // TODO: is this needed?
271969
+ layer: toNgLayerName(DataType$3.OBS_POINTS, layerScope)
271970
+ }
271971
+ };
271972
+ }
271973
+ });
271974
+ return result;
271975
+ }, {
271976
+ theme,
271977
+ segmentationLayerScopes,
271978
+ segmentationChannelScopesByLayer,
271979
+ segmentationLayerCoordination,
271980
+ segmentationChannelCoordination,
271981
+ obsSegmentationsUrls,
271982
+ obsSegmentationsData,
271983
+ pointLayerScopes,
271984
+ pointLayerCoordination,
271985
+ obsPointsUrls,
271986
+ obsPointsData,
271987
+ pointMultiIndicesData
271988
+ }, customIsEqualForInitialViewerState);
271989
+ return viewerState;
271517
271990
  }
271518
271991
  /**
271519
271992
  * @license
@@ -301187,9 +301660,29 @@ function rgbToHex$1(rgb2) {
301187
301660
  return typeof rgb2 === "string" ? rgb2 : `#${rgb2.map((c2) => c2.toString(16).padStart(2, "0")).join("")}`;
301188
301661
  }
301189
301662
  function NeuroglancerSubscriber(props) {
301190
- const { coordinationScopes: coordinationScopesRaw, closeButtonVisible, downloadButtonVisible, removeGridComponent, theme, title: title2 = "Neuroglancer", helpText = ViewHelpMapping.NEUROGLANCER } = props;
301663
+ const {
301664
+ uuid: uuid2,
301665
+ coordinationScopes: coordinationScopesRaw,
301666
+ coordinationScopesBy: coordinationScopesByRaw,
301667
+ closeButtonVisible,
301668
+ downloadButtonVisible,
301669
+ removeGridComponent,
301670
+ theme,
301671
+ title: title2 = "Spatial",
301672
+ subtitle = "Powered by Neuroglancer",
301673
+ helpText = ViewHelpMapping.NEUROGLANCER,
301674
+ // Note: this is a temporary mechanism
301675
+ // to pass an initial NG camera state.
301676
+ // Ideally, all camera state should be passed via
301677
+ // the existing spatialZoom, spatialTargetX, spatialRotationOrbit, etc,
301678
+ // and then NeuroglancerSubscriber should internally convert
301679
+ // to NG-compatible values, which would eliminate the need for this.
301680
+ initialNgCameraState
301681
+ } = props;
301191
301682
  const loaders = useLoaders();
301683
+ const mergeCoordination = useMergeCoordination();
301192
301684
  const coordinationScopes = useCoordinationScopes(coordinationScopesRaw);
301685
+ const coordinationScopesBy = useCoordinationScopesBy(coordinationScopes, coordinationScopesByRaw);
301193
301686
  const [{
301194
301687
  dataset,
301195
301688
  obsType,
@@ -301219,11 +301712,129 @@ function NeuroglancerSubscriber(props) {
301219
301712
  setSpatialRotationOrbit: setRotationOrbit,
301220
301713
  setSpatialZoom: setZoom
301221
301714
  }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType$1.NEUROGLANCER], coordinationScopes);
301715
+ const [ngWidth, ngHeight, containerRef] = useGridItemSize();
301716
+ const [segmentationLayerScopes, segmentationChannelScopesByLayer] = useMultiCoordinationScopesSecondaryNonNull(CoordinationType$1.SEGMENTATION_CHANNEL, CoordinationType$1.SEGMENTATION_LAYER, coordinationScopes, coordinationScopesBy);
301717
+ const pointLayerScopes = useMultiCoordinationScopesNonNull(CoordinationType$1.POINT_LAYER, coordinationScopes);
301718
+ const segmentationLayerCoordination = useComplexCoordination([
301719
+ CoordinationType$1.FILE_UID,
301720
+ CoordinationType$1.SEGMENTATION_CHANNEL,
301721
+ CoordinationType$1.SPATIAL_LAYER_VISIBLE,
301722
+ CoordinationType$1.SPATIAL_LAYER_OPACITY
301723
+ ], coordinationScopes, coordinationScopesBy, CoordinationType$1.SEGMENTATION_LAYER);
301724
+ const segmentationChannelCoordination = useComplexCoordinationSecondary([
301725
+ CoordinationType$1.OBS_TYPE,
301726
+ CoordinationType$1.SPATIAL_TARGET_C,
301727
+ CoordinationType$1.SPATIAL_CHANNEL_VISIBLE,
301728
+ CoordinationType$1.SPATIAL_CHANNEL_OPACITY,
301729
+ CoordinationType$1.SPATIAL_CHANNEL_COLOR,
301730
+ CoordinationType$1.SPATIAL_SEGMENTATION_FILLED,
301731
+ CoordinationType$1.SPATIAL_SEGMENTATION_STROKE_WIDTH,
301732
+ CoordinationType$1.OBS_COLOR_ENCODING,
301733
+ CoordinationType$1.FEATURE_SELECTION,
301734
+ CoordinationType$1.FEATURE_AGGREGATION_STRATEGY,
301735
+ CoordinationType$1.FEATURE_VALUE_COLORMAP,
301736
+ CoordinationType$1.FEATURE_VALUE_COLORMAP_RANGE,
301737
+ CoordinationType$1.OBS_SET_COLOR,
301738
+ CoordinationType$1.OBS_SET_SELECTION,
301739
+ CoordinationType$1.ADDITIONAL_OBS_SETS,
301740
+ CoordinationType$1.OBS_HIGHLIGHT,
301741
+ CoordinationType$1.TOOLTIPS_VISIBLE,
301742
+ CoordinationType$1.TOOLTIP_CROSSHAIRS_VISIBLE,
301743
+ CoordinationType$1.LEGEND_VISIBLE
301744
+ ], coordinationScopes, coordinationScopesBy, CoordinationType$1.SEGMENTATION_LAYER, CoordinationType$1.SEGMENTATION_CHANNEL);
301745
+ const pointLayerCoordination = useComplexCoordination([
301746
+ CoordinationType$1.OBS_TYPE,
301747
+ CoordinationType$1.SPATIAL_LAYER_VISIBLE,
301748
+ CoordinationType$1.SPATIAL_LAYER_OPACITY,
301749
+ CoordinationType$1.OBS_COLOR_ENCODING,
301750
+ CoordinationType$1.FEATURE_COLOR,
301751
+ CoordinationType$1.FEATURE_FILTER_MODE,
301752
+ CoordinationType$1.FEATURE_SELECTION,
301753
+ CoordinationType$1.FEATURE_VALUE_COLORMAP,
301754
+ CoordinationType$1.FEATURE_VALUE_COLORMAP_RANGE,
301755
+ CoordinationType$1.SPATIAL_LAYER_COLOR,
301756
+ CoordinationType$1.OBS_HIGHLIGHT,
301757
+ CoordinationType$1.TOOLTIPS_VISIBLE,
301758
+ CoordinationType$1.TOOLTIP_CROSSHAIRS_VISIBLE,
301759
+ CoordinationType$1.LEGEND_VISIBLE
301760
+ ], coordinationScopes, coordinationScopesBy, CoordinationType$1.POINT_LAYER);
301761
+ const [obsPointsData, obsPointsDataStatus, obsPointsUrls, obsPointsErrors] = useMultiObsPoints(coordinationScopes, coordinationScopesBy, loaders, dataset, mergeCoordination, uuid2);
301762
+ const [pointMultiIndicesData, pointMultiIndicesDataStatus, pointMultiIndicesDataErrors] = usePointMultiObsFeatureMatrixIndices(coordinationScopes, coordinationScopesBy, loaders, dataset);
301763
+ const [obsSegmentationsData, obsSegmentationsDataStatus, obsSegmentationsUrls, obsSegmentationsDataErrors] = useMultiObsSegmentations(coordinationScopes, coordinationScopesBy, loaders, dataset, mergeCoordination, uuid2);
301764
+ const [obsSegmentationsSetsData, obsSegmentationsSetsDataStatus, obsSegmentationsSetsDataErrors] = useSegmentationMultiObsSets(coordinationScopes, coordinationScopesBy, loaders, dataset);
301765
+ const [segmentationMultiExpressionData, segmentationMultiLoadedFeatureSelection, segmentationMultiExpressionExtents, segmentationMultiExpressionNormData, segmentationMultiFeatureSelectionStatus, segmentationMultiFeatureSelectionErrors] = useSegmentationMultiFeatureSelection(coordinationScopes, coordinationScopesBy, loaders, dataset);
301766
+ const [segmentationMultiIndicesData, segmentationMultiIndicesDataStatus, segmentationMultiIndicesDataErrors] = useSegmentationMultiObsFeatureMatrixIndices(coordinationScopes, coordinationScopesBy, loaders, dataset);
301767
+ const errors = [
301768
+ ...obsPointsErrors,
301769
+ ...obsSegmentationsDataErrors,
301770
+ ...obsSegmentationsSetsDataErrors,
301771
+ ...pointMultiIndicesDataErrors,
301772
+ ...segmentationMultiFeatureSelectionErrors,
301773
+ ...segmentationMultiIndicesDataErrors
301774
+ ];
301775
+ const isReady = useReady([
301776
+ // Points
301777
+ obsPointsDataStatus,
301778
+ pointMultiIndicesDataStatus,
301779
+ // Segmentations
301780
+ obsSegmentationsDataStatus,
301781
+ obsSegmentationsSetsDataStatus,
301782
+ segmentationMultiFeatureSelectionStatus,
301783
+ segmentationMultiIndicesDataStatus
301784
+ ]);
301222
301785
  const { classes: classes2 } = useStyles$4();
301223
- const [{ obsSets: cellSets }] = useObsSetsData(loaders, dataset, false, { setObsSetSelection: setCellSetSelection, setObsSetColor: setCellSetColor }, { cellSetSelection, obsSetColor: cellSetColor }, { obsType });
301224
- const [{ obsIndex }] = useObsEmbeddingData(loaders, dataset, true, {}, {}, { obsType, embeddingType: mapping });
301225
- const [initalViewerState] = useNeuroglancerViewerState(loaders, dataset);
301226
- const latestViewerStateRef = useRef(initalViewerState);
301786
+ const segmentationColorMapping = useMemoCustomComparison(() => {
301787
+ const result = {};
301788
+ segmentationLayerScopes?.forEach((layerScope) => {
301789
+ result[layerScope] = {};
301790
+ segmentationChannelScopesByLayer?.[layerScope]?.forEach((channelScope) => {
301791
+ const { obsSets: layerSets, obsIndex: layerIndex } = obsSegmentationsSetsData?.[layerScope]?.[channelScope] || {};
301792
+ if (layerSets && layerIndex) {
301793
+ const { obsSetColor, obsColorEncoding, obsSetSelection, additionalObsSets } = segmentationChannelCoordination[0][layerScope][channelScope];
301794
+ const mergedCellSets = mergeObsSets(layerSets, additionalObsSets);
301795
+ const cellColors = getCellColors({
301796
+ cellSets: mergedCellSets,
301797
+ cellSetSelection: obsSetSelection,
301798
+ cellSetColor: obsSetColor,
301799
+ obsIndex: layerIndex,
301800
+ theme
301801
+ });
301802
+ const ngCellColors = {};
301803
+ cellColors.forEach((color2, i2) => {
301804
+ ngCellColors[i2] = rgbToHex$1(color2);
301805
+ });
301806
+ result[layerScope][channelScope] = ngCellColors;
301807
+ }
301808
+ });
301809
+ });
301810
+ return result;
301811
+ }, {
301812
+ // The dependencies for the comparison,
301813
+ // used by the custom equality function.
301814
+ segmentationLayerScopes,
301815
+ segmentationChannelScopesByLayer,
301816
+ obsSegmentationsSetsData,
301817
+ segmentationChannelCoordination,
301818
+ theme
301819
+ }, customIsEqualForCellColors);
301820
+ const initalViewerState = useNeuroglancerViewerState(theme, segmentationLayerScopes, segmentationChannelScopesByLayer, segmentationLayerCoordination, segmentationChannelCoordination, obsSegmentationsUrls, obsSegmentationsData, pointLayerScopes, pointLayerCoordination, obsPointsUrls, obsPointsData, pointMultiIndicesData);
301821
+ const [latestViewerStateIteration, incrementLatestViewerStateIteration] = useReducer((x2) => x2 + 1, 0);
301822
+ const latestViewerStateRef = useRef({
301823
+ ...initalViewerState,
301824
+ ...initialNgCameraState ?? {}
301825
+ });
301826
+ useEffect(() => {
301827
+ const prevNgCameraState = {
301828
+ position: latestViewerStateRef.current.position,
301829
+ projectionOrientation: latestViewerStateRef.current.projectionOrientation,
301830
+ projectionScale: latestViewerStateRef.current.projectionScale
301831
+ };
301832
+ latestViewerStateRef.current = {
301833
+ ...initalViewerState,
301834
+ ...prevNgCameraState
301835
+ };
301836
+ incrementLatestViewerStateIteration();
301837
+ }, [initalViewerState]);
301227
301838
  const initialRotationPushedRef = useRef(false);
301228
301839
  const ngRotPushAtRef = useRef(0);
301229
301840
  const lastInteractionSource = useRef(null);
@@ -301249,20 +301860,6 @@ function NeuroglancerSubscriber(props) {
301249
301860
  tx: spatialTargetX,
301250
301861
  ty: spatialTargetY
301251
301862
  });
301252
- const mergedCellSets = useMemo$1(() => mergeObsSets(cellSets, additionalCellSets), [cellSets, additionalCellSets]);
301253
- const cellColors = useMemo$1(() => getCellColors({
301254
- cellSets: mergedCellSets,
301255
- cellSetSelection,
301256
- cellSetColor,
301257
- obsIndex,
301258
- theme
301259
- }), [
301260
- mergedCellSets,
301261
- theme,
301262
- cellSetColor,
301263
- cellSetSelection,
301264
- obsIndex
301265
- ]);
301266
301863
  const handleStateUpdate = useCallback((newState) => {
301267
301864
  lastInteractionSource.current = LAST_INTERACTION_SOURCE.neuroglancer;
301268
301865
  const { projectionScale, projectionOrientation, position: position2 } = newState;
@@ -301354,25 +301951,12 @@ function NeuroglancerSubscriber(props) {
301354
301951
  setCellSetColor,
301355
301952
  setCellSetSelection
301356
301953
  ]);
301357
- const batchedUpdateTimeoutRef = useRef(null);
301358
- const [batchedCellColors, setBatchedCellColors] = useState(cellColors);
301359
- useEffect(() => {
301360
- if (batchedUpdateTimeoutRef.current) {
301361
- clearTimeout(batchedUpdateTimeoutRef.current);
301362
- }
301363
- batchedUpdateTimeoutRef.current = setTimeout(() => {
301364
- setBatchedCellColors(cellColors);
301365
- }, 100);
301366
- }, [cellColors]);
301367
- const cellColorMapping = useMemo$1(() => {
301368
- const colorMapping = {};
301369
- batchedCellColors.forEach((color2, cell2) => {
301370
- colorMapping[cell2] = rgbToHex$1(color2);
301371
- });
301372
- return colorMapping;
301373
- }, [batchedCellColors]);
301954
+ const cellColorMapping = useMemo$1(() => segmentationColorMapping?.[segmentationLayerScopes?.[0]]?.[segmentationChannelScopesByLayer?.[segmentationLayerScopes?.[0]]?.[0]] ?? {}, [segmentationColorMapping]);
301374
301955
  const derivedViewerState = useMemo$1(() => {
301375
301956
  const { current: current2 } = latestViewerStateRef;
301957
+ if (current2.layers.length <= 0) {
301958
+ return current2;
301959
+ }
301376
301960
  const nextSegments = Object.keys(cellColorMapping);
301377
301961
  const prevLayer = current2?.layers?.[0] || {};
301378
301962
  const prevSegments = prevLayer.segments || [];
@@ -301458,12 +302042,15 @@ function NeuroglancerSubscriber(props) {
301458
302042
  spatialRotationY,
301459
302043
  spatialRotationZ,
301460
302044
  spatialTargetX,
301461
- spatialTargetY
302045
+ spatialTargetY,
302046
+ initalViewerState,
302047
+ latestViewerStateIteration
301462
302048
  ]);
301463
302049
  const onSegmentHighlight = useCallback((obsId) => {
301464
302050
  setCellHighlight(String(obsId));
301465
- }, [obsIndex, setCellHighlight]);
301466
- return jsxRuntimeExports.jsx(TitleInfo, { title: title2, helpText, isSpatial: true, theme, closeButtonVisible, downloadButtonVisible, removeGridComponent, isReady: true, withPadding: false, children: jsxRuntimeExports.jsx(NeuroglancerComp, { classes: classes2, onSegmentClick, onSelectHoveredCoords: onSegmentHighlight, viewerState: derivedViewerState, cellColorMapping, setViewerState: handleStateUpdate }) });
302051
+ }, [setCellHighlight]);
302052
+ const hasLayers = derivedViewerState?.layers?.length > 0;
302053
+ return jsxRuntimeExports.jsx(TitleInfo, { title: title2, info: subtitle, helpText, isSpatial: true, theme, closeButtonVisible, downloadButtonVisible, removeGridComponent, isReady, errors, withPadding: false, children: jsxRuntimeExports.jsxs("div", { style: { position: "relative", width: "100%", height: "100%" }, ref: containerRef, children: [jsxRuntimeExports.jsx("div", { style: { position: "absolute", top: 0, right: 0, zIndex: 50 }, children: jsxRuntimeExports.jsx(MultiLegend, { theme: "dark", maxHeight: ngHeight, segmentationLayerScopes, segmentationLayerCoordination, segmentationChannelScopesByLayer, segmentationChannelCoordination }) }), hasLayers ? jsxRuntimeExports.jsx(NeuroglancerComp, { classes: classes2, onSegmentClick, onSelectHoveredCoords: onSegmentHighlight, viewerState: derivedViewerState, cellColorMapping, setViewerState: handleStateUpdate }) : null] }) });
301467
302054
  }
301468
302055
  const FEATURE_AGGREGATION_STRATEGIES = ["first", "last", "sum", "mean"];
301469
302056
  function CellSetExpressionPlotOptions(props) {
@@ -356468,7 +357055,7 @@ class ObsSpotsCsvLoader extends CsvLoader {
356468
357055
  const payload = await this.getSourceData();
356469
357056
  const coordinationValues = {
356470
357057
  spotLayer: CL({
356471
- obsType: "spot",
357058
+ obsType: this.coordinationValues?.obsType ?? "spot",
356472
357059
  // obsColorEncoding: 'spatialLayerColor',
356473
357060
  // spatialLayerColor: [255, 255, 255],
356474
357061
  spatialLayerVisible: true,
@@ -356508,7 +357095,7 @@ class ObsPointsCsvLoader extends CsvLoader {
356508
357095
  const payload = await this.getSourceData();
356509
357096
  const coordinationValues = {
356510
357097
  pointLayer: CL({
356511
- obsType: "point",
357098
+ obsType: this.coordinationValues?.obsType ?? "point",
356512
357099
  // obsColorEncoding: 'spatialLayerColor',
356513
357100
  // spatialLayerColor: [255, 255, 255],
356514
357101
  spatialLayerVisible: true,
@@ -358074,7 +358661,7 @@ class ObsSpotsAnndataLoader extends AbstractTwoStepLoader {
358074
358661
  const { path: path2 } = this.options;
358075
358662
  const coordinationValues = {
358076
358663
  spotLayer: CL({
358077
- obsType: "spot",
358664
+ obsType: this.coordinationValues?.obsType ?? "spot",
358078
358665
  // obsColorEncoding: 'spatialLayerColor',
358079
358666
  // spatialLayerColor: [255, 255, 255],
358080
358667
  spatialLayerVisible: true,
@@ -358118,7 +358705,7 @@ class ObsPointsAnndataLoader extends AbstractTwoStepLoader {
358118
358705
  const { path: path2 } = this.options;
358119
358706
  const coordinationValues = {
358120
358707
  pointLayer: CL({
358121
- obsType: "point",
358708
+ obsType: this.coordinationValues?.obsType ?? "point",
358122
358709
  // obsColorEncoding: 'spatialLayerColor',
358123
358710
  // spatialLayerColor: [255, 255, 255],
358124
358711
  spatialLayerVisible: true,
@@ -359605,7 +360192,7 @@ class SpatialDataObsSpotsLoader extends AbstractTwoStepLoader {
359605
360192
  const spatialSpotRadius = obsRadius?.data?.[0];
359606
360193
  const coordinationValues = {
359607
360194
  spotLayer: CL({
359608
- obsType: "spot",
360195
+ obsType: this.coordinationValues?.obsType ?? "spot",
359609
360196
  // obsColorEncoding: 'spatialLayerColor',
359610
360197
  // spatialLayerColor: [255, 255, 255],
359611
360198
  spatialLayerVisible: true,
@@ -359820,7 +360407,7 @@ class SpatialDataObsPointsLoader extends AbstractTwoStepLoader {
359820
360407
  ]);
359821
360408
  const coordinationValues = {
359822
360409
  pointLayer: CL({
359823
- obsType: "point",
360410
+ obsType: this.coordinationValues?.obsType ?? "point",
359824
360411
  obsColorEncoding: "spatialLayerColor",
359825
360412
  spatialLayerColor: [255, 255, 255],
359826
360413
  spatialLayerVisible: true,
@@ -359888,12 +360475,26 @@ class PrecomputedMeshSource {
359888
360475
  }
359889
360476
  }
359890
360477
  class PrecomputedMeshDataLoader extends AbstractTwoStepLoader {
359891
- /* eslint-disable class-methods-use-this */
359892
- async load(url) {
360478
+ async load() {
360479
+ const { url, options } = this;
359893
360480
  return new LoaderResult({
359894
360481
  obsIndex: null,
359895
360482
  obsSegmentations: {},
359896
- obsSegmentationsType: "mesh"
360483
+ obsSegmentationsType: "mesh",
360484
+ neuroglancerOptions: options
360485
+ }, url);
360486
+ }
360487
+ }
360488
+ class NgAnnotationPointsDataLoader extends AbstractTwoStepLoader {
360489
+ async load() {
360490
+ const { url, options } = this;
360491
+ return new LoaderResult({
360492
+ obsIndex: null,
360493
+ obsPoints: null,
360494
+ featureIds: null,
360495
+ obsPointsModelMatrix: null,
360496
+ obsPointsTilingType: "neuroglancer",
360497
+ neuroglancerOptions: options
359897
360498
  }, url);
359898
360499
  }
359899
360500
  }
@@ -381852,7 +382453,8 @@ const baseFileTypes = [
381852
382453
  ...makeZarrFileTypes(FileType$1.OBS_EMBEDDING_SPATIALDATA_ZARR, DataType$3.OBS_EMBEDDING, SpatialDataObsEmbeddingLoader, SpatialDataTableSource, obsEmbeddingSpatialdataSchema),
381853
382454
  ...makeZarrFileTypes(FileType$1.FEATURE_LABELS_SPATIALDATA_ZARR, DataType$3.FEATURE_LABELS, SpatialDataFeatureLabelsLoader, SpatialDataTableSource, featureLabelsAnndataSchema),
381854
382455
  makeFileType(FileType$1.OBS_SEGMENTATIONS_GLB, DataType$3.OBS_SEGMENTATIONS, GlbDataLoader, GlbSource, meshGlbSchema),
381855
- makeFileType(FileType$1.OBS_SEGMENTATIONS_NG_PRECOMPUTED, DataType$3.OBS_SEGMENTATIONS, PrecomputedMeshDataLoader, PrecomputedMeshSource, ngSchema),
382456
+ makeFileType(FileType$1.OBS_SEGMENTATIONS_NG_PRECOMPUTED, DataType$3.OBS_SEGMENTATIONS, PrecomputedMeshDataLoader, PrecomputedMeshSource, ngPrecomputedMeshSchema),
382457
+ makeFileType(FileType$1.OBS_POINTS_NG_ANNOTATIONS, DataType$3.OBS_POINTS, NgAnnotationPointsDataLoader, PrecomputedMeshSource, ngPointAnnotationSchema),
381856
382458
  // All legacy file types
381857
382459
  makeFileType(FileType$1.OBS_FEATURE_MATRIX_EXPRESSION_MATRIX_ZARR, DataType$3.OBS_FEATURE_MATRIX, MatrixZarrAsObsFeatureMatrixLoader, ZarrDataSource, z.null()),
381858
382460
  makeFileType(FileType$1.IMAGE_RASTER_JSON, DataType$3.IMAGE, RasterJsonAsImageLoader, JsonSource, rasterJsonSchema),