@vitessce/all 4.1.0 → 4.1.1

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.
Files changed (29) hide show
  1. package/dist/{GeometryAndMeshXR-Cm-io8sr.js → GeometryAndMeshXR-BSJ2rBtK.js} +1 -1
  2. package/dist/{ReactNeuroglancer-CGw5kiSQ.js → ReactNeuroglancer-Db7O0CnI.js} +5 -3
  3. package/dist/{XREnterButton-Cvh0jhTZ.js → XREnterButton-D-MyjNiM.js} +1 -1
  4. package/dist/{XRSceneComponents-D1dNWCd8.js → XRSceneComponents-KvBqtraG.js} +1 -1
  5. package/dist/{XRWrapper-DMvuX589.js → XRWrapper-BNdj_qnt.js} +2 -2
  6. package/dist/{deflate-Bfp4Ro1o.js → deflate-B9RQRiyy.js} +1 -1
  7. package/dist/{higlass-R6f4spnl.js → higlass-CJExboBo.js} +1 -1
  8. package/dist/{index-b1x98NVi.js → index-CZ9S9EsT.js} +1 -1
  9. package/dist/{index-BpNOtGFe.js → index-Vg2it-xm.js} +5 -5
  10. package/dist/{index-BXZvRgQM.js → index-uF7T9QQ9.js} +320 -66
  11. package/dist/index.js +6 -4
  12. package/dist/{jpeg-BshoD8Vn.js → jpeg-D1J1ZLjO.js} +1 -1
  13. package/dist/{lerc-Wpo0Q58k.js → lerc-BYUvdCVc.js} +1 -1
  14. package/dist/{lzw-bn_buOKr.js → lzw-BnX_a9ES.js} +1 -1
  15. package/dist/{packbits-CQxjn7MJ.js → packbits-DxNVm_vW.js} +1 -1
  16. package/dist/{raw-DuVejors.js → raw-D529ykG0.js} +1 -1
  17. package/dist/{webimage-BVwps2SV.js → webimage-D6fsjgI6.js} +1 -1
  18. package/dist/{xrStore-Cc3xse27.js → xrStore-2FzrFs3o.js} +1 -1
  19. package/dist-tsc/base-plugins.d.ts +1 -1
  20. package/dist-tsc/base-plugins.d.ts.map +1 -1
  21. package/dist-tsc/base-plugins.js +1 -0
  22. package/dist-tsc/base-plugins.js.map +1 -1
  23. package/dist-tsc/index.d.ts +1 -1
  24. package/dist-tsc/index.d.ts.map +1 -1
  25. package/dist-tsc/index.js +1 -1
  26. package/dist-tsc/index.js.map +1 -1
  27. package/package.json +34 -34
  28. package/src/base-plugins.ts +1 -0
  29. package/src/index.ts +2 -0
@@ -6803,6 +6803,19 @@ function isAnnotationFrameViewStateChange(prevViewState, nextViewState, frameVie
6803
6803
  const changedKeys = TRANSITION_VIEW_STATE_KEYS.filter((key2) => prevViewState[key2] !== nextViewState[key2]);
6804
6804
  return changedKeys.length > 0 && changedKeys.every((key2) => typeof prevViewState[key2] === "number" && typeof nextViewState[key2] === "number" && frameViewState[key2] === nextViewState[key2]);
6805
6805
  }
6806
+ const UNIT_TO_METERS = {
6807
+ m: 1,
6808
+ meter: 1,
6809
+ mm: 1e-3,
6810
+ millimeter: 1e-3,
6811
+ um: 1e-6,
6812
+ µm: 1e-6,
6813
+ μm: 1e-6,
6814
+ micrometer: 1e-6,
6815
+ micron: 1e-6,
6816
+ nm: 1e-9,
6817
+ nanometer: 1e-9
6818
+ };
6806
6819
  configSchema1_0_0.shape.coordinationSpace.unwrap();
6807
6820
  configSchema1_0_0.shape.layout.element.shape.coordinationScopes.unwrap();
6808
6821
  function upgradeReplaceViewProp(prefix2, view, coordinationSpace) {
@@ -9616,6 +9629,7 @@ const CoordinationType$1 = {
9616
9629
  PIXEL_HIGHLIGHT: "pixelHighlight",
9617
9630
  // Per-image-layer
9618
9631
  TOOLTIP_CROSSHAIRS_VISIBLE: "tooltipCrosshairsVisible",
9632
+ TOOLTIP_OBS_SETS_MODE: "tooltipObsSetsMode",
9619
9633
  LEGEND_VISIBLE: "legendVisible",
9620
9634
  SPATIAL_CHANNEL_LABELS_VISIBLE: "spatialChannelLabelsVisible",
9621
9635
  SPATIAL_CHANNEL_LABELS_ORIENTATION: "spatialChannelLabelsOrientation",
@@ -9977,6 +9991,7 @@ const COMPONENT_COORDINATION_TYPES = {
9977
9991
  CoordinationType$1.SPATIAL_ORBIT_AXIS,
9978
9992
  CoordinationType$1.SPATIAL_ZOOM,
9979
9993
  CoordinationType$1.SPATIAL_CAMERA_SNAPSHOT,
9994
+ CoordinationType$1.SPATIAL_RENDERING_MODE,
9980
9995
  CoordinationType$1.OBS_FILTER,
9981
9996
  CoordinationType$1.OBS_HIGHLIGHT,
9982
9997
  CoordinationType$1.OBS_SET_SELECTION,
@@ -10044,6 +10059,7 @@ const COMPONENT_COORDINATION_TYPES = {
10044
10059
  CoordinationType$1.OBS_COLOR_ENCODING,
10045
10060
  CoordinationType$1.ADDITIONAL_OBS_SETS,
10046
10061
  CoordinationType$1.TOOLTIPS_VISIBLE,
10062
+ CoordinationType$1.TOOLTIP_OBS_SETS_MODE,
10047
10063
  CoordinationType$1.SAMPLE_TYPE,
10048
10064
  CoordinationType$1.SAMPLE_SET_SELECTION,
10049
10065
  CoordinationType$1.SAMPLE_SET_FILTER,
@@ -10095,6 +10111,7 @@ const COMPONENT_COORDINATION_TYPES = {
10095
10111
  CoordinationType$1.OBS_COLOR_ENCODING,
10096
10112
  CoordinationType$1.ADDITIONAL_OBS_SETS,
10097
10113
  CoordinationType$1.TOOLTIPS_VISIBLE,
10114
+ CoordinationType$1.TOOLTIP_OBS_SETS_MODE,
10098
10115
  CoordinationType$1.SAMPLE_TYPE,
10099
10116
  CoordinationType$1.SAMPLE_SET_SELECTION,
10100
10117
  CoordinationType$1.SAMPLE_SET_FILTER,
@@ -10176,6 +10193,7 @@ const COMPONENT_COORDINATION_TYPES = {
10176
10193
  CoordinationType$1.ADDITIONAL_OBS_SETS,
10177
10194
  CoordinationType$1.MOLECULE_HIGHLIGHT,
10178
10195
  CoordinationType$1.TOOLTIPS_VISIBLE,
10196
+ CoordinationType$1.TOOLTIP_OBS_SETS_MODE,
10179
10197
  CoordinationType$1.PHOTOMETRIC_INTERPRETATION,
10180
10198
  CoordinationType$1.ANNOTATION_STORY,
10181
10199
  CoordinationType$1.ANNOTATION_SHAPES,
@@ -10225,6 +10243,7 @@ const COMPONENT_COORDINATION_TYPES = {
10225
10243
  CoordinationType$1.ADDITIONAL_OBS_SETS,
10226
10244
  CoordinationType$1.MOLECULE_HIGHLIGHT,
10227
10245
  CoordinationType$1.TOOLTIPS_VISIBLE,
10246
+ CoordinationType$1.TOOLTIP_OBS_SETS_MODE,
10228
10247
  CoordinationType$1.FILE_UID,
10229
10248
  CoordinationType$1.SPATIAL_TARGET_C,
10230
10249
  CoordinationType$1.SPATIAL_LAYER_VISIBLE,
@@ -10308,7 +10327,8 @@ const COMPONENT_COORDINATION_TYPES = {
10308
10327
  CoordinationType$1.FEATURE_VALUE_COLORMAP_RANGE,
10309
10328
  CoordinationType$1.OBS_COLOR_ENCODING,
10310
10329
  CoordinationType$1.ADDITIONAL_OBS_SETS,
10311
- CoordinationType$1.TOOLTIPS_VISIBLE
10330
+ CoordinationType$1.TOOLTIPS_VISIBLE,
10331
+ CoordinationType$1.TOOLTIP_OBS_SETS_MODE
10312
10332
  ],
10313
10333
  [ViewType$1.OBS_SETS]: [
10314
10334
  CoordinationType$1.DATASET,
@@ -93190,6 +93210,12 @@ function findChangedHierarchy(prevSelectedPaths, currSelectedPaths) {
93190
93210
  const changedPath = newlySelectedPaths.length > 0 ? newlySelectedPaths[0] : unselectedPaths[0];
93191
93211
  return changedPath.slice(0, -1);
93192
93212
  }
93213
+ function filterObsMembershipForTooltip(obsMembership, obsSetSelection, tooltipObsSetsMode) {
93214
+ if (tooltipObsSetsMode !== "selected") {
93215
+ return obsMembership;
93216
+ }
93217
+ return obsMembership.filter((path2) => obsSetSelection?.some((selectedPath) => selectedPath[0] === path2[0]));
93218
+ }
93193
93219
  var EOL$1 = {}, EOF$1 = {}, QUOTE$1 = 34, NEWLINE$1 = 10, RETURN$1 = 13;
93194
93220
  function objectConverter$1(columns2) {
93195
93221
  return new Function("d", "return {" + columns2.map(function(name2, i2) {
@@ -210886,22 +210912,22 @@ async function getDecoder(fileDirectory) {
210886
210912
  const Decoder = await importFn();
210887
210913
  return new Decoder(fileDirectory);
210888
210914
  }
210889
- addDecoder([void 0, 1], () => import("./raw-DuVejors.js").then((m2) => m2.default));
210890
- addDecoder(5, () => import("./lzw-bn_buOKr.js").then((m2) => m2.default));
210915
+ addDecoder([void 0, 1], () => import("./raw-D529ykG0.js").then((m2) => m2.default));
210916
+ addDecoder(5, () => import("./lzw-BnX_a9ES.js").then((m2) => m2.default));
210891
210917
  addDecoder(6, () => {
210892
210918
  throw new Error("old style JPEG compression is not supported.");
210893
210919
  });
210894
- addDecoder(7, () => import("./jpeg-BshoD8Vn.js").then((m2) => m2.default));
210895
- addDecoder([8, 32946], () => import("./deflate-Bfp4Ro1o.js").then((m2) => m2.default));
210896
- addDecoder(32773, () => import("./packbits-CQxjn7MJ.js").then((m2) => m2.default));
210920
+ addDecoder(7, () => import("./jpeg-D1J1ZLjO.js").then((m2) => m2.default));
210921
+ addDecoder([8, 32946], () => import("./deflate-B9RQRiyy.js").then((m2) => m2.default));
210922
+ addDecoder(32773, () => import("./packbits-DxNVm_vW.js").then((m2) => m2.default));
210897
210923
  addDecoder(
210898
210924
  34887,
210899
- () => import("./lerc-Wpo0Q58k.js").then(async (m2) => {
210925
+ () => import("./lerc-BYUvdCVc.js").then(async (m2) => {
210900
210926
  await m2.zstd.init();
210901
210927
  return m2;
210902
210928
  }).then((m2) => m2.default)
210903
210929
  );
210904
- addDecoder(50001, () => import("./webimage-BVwps2SV.js").then((m2) => m2.default));
210930
+ addDecoder(50001, () => import("./webimage-D6fsjgI6.js").then((m2) => m2.default));
210905
210931
  function copyNewSize(array2, width2, height2, samplesPerPixel = 1) {
210906
210932
  return new (Object.getPrototypeOf(array2)).constructor(width2 * height2 * samplesPerPixel);
210907
210933
  }
@@ -233323,6 +233349,7 @@ class AbstractSpatialOrScatterplot extends PureComponent {
233323
233349
  };
233324
233350
  this.lastApplied = null;
233325
233351
  this.transitionEndViewState = null;
233352
+ this.finishedTransitionEndViewState = null;
233326
233353
  this.viewport = null;
233327
233354
  this.threeCamera = null;
233328
233355
  this.orbitControls = null;
@@ -233399,6 +233426,7 @@ class AbstractSpatialOrScatterplot extends PureComponent {
233399
233426
  * Called by DeckGL when a viewState transition ends.
233400
233427
  */
233401
233428
  onTransitionEnd() {
233429
+ this.finishedTransitionEndViewState = this.transitionEndViewState;
233402
233430
  this.transitionEndViewState = null;
233403
233431
  this.setState({ transitionViewState: null });
233404
233432
  }
@@ -233409,6 +233437,7 @@ class AbstractSpatialOrScatterplot extends PureComponent {
233409
233437
  * Instead, the stale transitionViewState is ignored by getDeckViewState.
233410
233438
  */
233411
233439
  onTransitionInterrupt() {
233440
+ this.finishedTransitionEndViewState = this.transitionEndViewState;
233412
233441
  this.transitionEndViewState = null;
233413
233442
  }
233414
233443
  /**
@@ -233421,6 +233450,13 @@ class AbstractSpatialOrScatterplot extends PureComponent {
233421
233450
  if (transitionViewState && transitionViewState.endViewState === this.transitionEndViewState && isSameZoomAndTarget(viewState, this.transitionEndViewState)) {
233422
233451
  return transitionViewState.viewState;
233423
233452
  }
233453
+ if (!isSameZoomAndTarget(viewState, this.finishedTransitionEndViewState)) {
233454
+ this.finishedTransitionEndViewState = null;
233455
+ }
233456
+ if (this.finishedTransitionEndViewState) {
233457
+ const { transitionDuration, transitionInterpolator, ...viewStateWithoutTransition } = viewState;
233458
+ return viewStateWithoutTransition;
233459
+ }
233424
233460
  if (viewState.transitionDuration) {
233425
233461
  return {
233426
233462
  ...viewState,
@@ -233577,7 +233613,8 @@ class AbstractSpatialOrScatterplot extends PureComponent {
233577
233613
  const canvas = deckRef?.current?.deck?.canvas;
233578
233614
  if (!canvas || !spatialCameraSnapshot)
233579
233615
  return;
233580
- const camera = new PerspectiveCamera(spatialCameraSnapshot.fovDegrees, 1, 0.1, 1e5);
233616
+ const { fovDegrees, projectionScale } = spatialCameraSnapshot;
233617
+ const camera = new PerspectiveCamera(fovDegrees, 1, Math.max(projectionScale * 1e-4, 1e-3), Math.max(projectionScale * 100, 1e5));
233581
233618
  camera.updateProjectionMatrix();
233582
233619
  const eventTarget = canvas.parentElement ?? canvas;
233583
233620
  const controls = new OrbitControls(camera, eventTarget);
@@ -233732,8 +233769,8 @@ class AbstractSpatialOrScatterplot extends PureComponent {
233732
233769
  viewState: {
233733
233770
  viewMatrix: rawViewMatrix,
233734
233771
  fovy: fovDegrees,
233735
- near: 0.1,
233736
- far: 1e5
233772
+ near: Math.max(projectionScale * 1e-4, 1e-3),
233773
+ far: Math.max(projectionScale * 100, 1e5)
233737
233774
  }
233738
233775
  });
233739
233776
  } else if (use3d) {
@@ -239385,7 +239422,10 @@ const useStyles$r = makeStyles()(() => ({
239385
239422
  bottom: "0px",
239386
239423
  left: "0px",
239387
239424
  paddingLeft: "10px",
239388
- paddingBottom: "10px"
239425
+ paddingBottom: "10px",
239426
+ // Keep long channel names within the view so they can be truncated.
239427
+ maxWidth: "90%",
239428
+ boxSizing: "border-box"
239389
239429
  },
239390
239430
  channelNamesLegendLayer: {
239391
239431
  display: "flex"
@@ -239420,7 +239460,7 @@ function ChannelNamesLegend(props) {
239420
239460
  const channelNames = imageWrapperInstance?.getChannelNames();
239421
239461
  const channelIndex = imageWrapperInstance?.getChannelIndex(spatialTargetC);
239422
239462
  const channelName = channelIndex !== void 0 ? channelNames?.[channelIndex] : void 0;
239423
- return spatialLayerVisible && spatialChannelVisible && spatialChannelLabelsVisible ? jsx$1(Typography, { variant: "h6", className: classes2.channelNameText, style: {
239463
+ return spatialLayerVisible && spatialChannelVisible && spatialChannelLabelsVisible ? jsx$1(Typography, { variant: "h6", className: classes2.channelNameText, noWrap: true, title: channelName, style: {
239424
239464
  color: rgbColor,
239425
239465
  fontSize: `${spatialChannelLabelSize}px`
239426
239466
  }, children: channelName }, `${layerScope}-${cScope}-${channelIndex}-${rgbColor}`) : null;
@@ -239432,6 +239472,7 @@ const DEFAULT_FEATURE_AGGREGATION_STRATEGY$3 = "first";
239432
239472
  function EmbeddingScatterplotSubscriber(props) {
239433
239473
  const {
239434
239474
  uuid: uuid2,
239475
+ viewUid: viewUidFromProps,
239435
239476
  closeButtonVisible,
239436
239477
  downloadButtonVisible,
239437
239478
  removeGridComponent,
@@ -239448,18 +239489,19 @@ function EmbeddingScatterplotSubscriber(props) {
239448
239489
  // Passed down from the ancestor <Vitessce/> or <VitS/> component.
239449
239490
  areAnnotationsEditable
239450
239491
  } = props;
239492
+ const viewUid = viewUidFromProps ?? uuid2;
239451
239493
  const loaders = useLoaders();
239452
239494
  const [
239453
239495
  // eslint-disable-next-line no-unused-vars
239454
239496
  coordinationScopes,
239455
239497
  _coordinationScopesBy,
239456
239498
  coordinationValues
239457
- ] = useViewMapping(uuid2);
239499
+ ] = useViewMapping(viewUid);
239458
239500
  const setComponentHover = useSetComponentHover();
239459
239501
  const setComponentViewInfo = useSetComponentViewInfo(uuid2);
239460
- useAnnotationFrameCoordination(uuid2, coordinationScopes, coordinationValues);
239461
- const [{ dataset, obsType, featureType, featureValueType, sampleType, embeddingZoom: zoom2, embeddingTargetX: targetX2, embeddingTargetY: targetY2, embeddingTargetZ: targetZ, embeddingType: mapping, obsFilter: cellFilter, obsHighlight: cellHighlight, featureSelection: geneSelection, obsSetSelection: cellSetSelection, obsSetColor: cellSetColor, obsColorEncoding: cellColorEncoding, additionalObsSets: additionalCellSets, embeddingObsSetPolygonsVisible: cellSetPolygonsVisible, embeddingObsSetLabelsVisible: cellSetLabelsVisible, embeddingObsSetLabelSize: cellSetLabelSize, embeddingObsRadius: cellRadiusFixed, embeddingObsRadiusMode: cellRadiusMode, embeddingObsOpacity: cellOpacityFixed, embeddingObsOpacityMode: cellOpacityMode, featureValueColormap: geneExpressionColormap, featureValueColormapRange: geneExpressionColormapRange, tooltipsVisible, sampleSetSelection: sampleSetSelectionFromCoordination, sampleSetColor, embeddingPointsVisible, embeddingContoursVisible, embeddingContoursFilled, embeddingContourPercentiles: contourPercentiles, contourColorEncoding, contourColor, featureAggregationStrategy, annotationStory, annotationShapes, annotationOverlayVisible, annotationSemanticZoom, annotationTransitionDuration, annotationEditable, annotationFrameIndex }, { setEmbeddingZoom: setZoom, setEmbeddingTargetX: setTargetX, setEmbeddingTargetY: setTargetY, setEmbeddingTargetZ: setTargetZ, setObsFilter: setCellFilter, setObsSetSelection: setCellSetSelection, setObsHighlight: setCellHighlight, setObsSetColor: setCellSetColor, setObsColorEncoding: setCellColorEncoding, setAdditionalObsSets: setAdditionalCellSets, setEmbeddingObsSetPolygonsVisible: setCellSetPolygonsVisible, setEmbeddingObsSetLabelsVisible: setCellSetLabelsVisible, setEmbeddingObsSetLabelSize: setCellSetLabelSize, setEmbeddingObsRadius: setCellRadiusFixed, setEmbeddingObsRadiusMode: setCellRadiusMode, setEmbeddingObsOpacity: setCellOpacityFixed, setEmbeddingObsOpacityMode: setCellOpacityMode, setFeatureValueColormap: setGeneExpressionColormap, setFeatureValueColormapRange: setGeneExpressionColormapRange, setTooltipsVisible, setEmbeddingPointsVisible, setEmbeddingContoursVisible, setEmbeddingContoursFilled, setEmbeddingContourPercentiles: setContourPercentiles, setContourColorEncoding, setFeatureAggregationStrategy, setAnnotationStory }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType$1.SCATTERPLOT], coordinationScopes, coordinationValues, uuid2);
239462
- const annotationEditingProps = useAnnotationEditingForView(uuid2, Boolean(areAnnotationsEditable && annotationEditable && typeof annotationFrameIndex === "number"));
239502
+ useAnnotationFrameCoordination(viewUid, coordinationScopes, coordinationValues);
239503
+ const [{ dataset, obsType, featureType, featureValueType, sampleType, embeddingZoom: zoom2, embeddingTargetX: targetX2, embeddingTargetY: targetY2, embeddingTargetZ: targetZ, embeddingType: mapping, obsFilter: cellFilter, obsHighlight: cellHighlight, featureSelection: geneSelection, obsSetSelection: cellSetSelection, obsSetColor: cellSetColor, obsColorEncoding: cellColorEncoding, additionalObsSets: additionalCellSets, embeddingObsSetPolygonsVisible: cellSetPolygonsVisible, embeddingObsSetLabelsVisible: cellSetLabelsVisible, embeddingObsSetLabelSize: cellSetLabelSize, embeddingObsRadius: cellRadiusFixed, embeddingObsRadiusMode: cellRadiusMode, embeddingObsOpacity: cellOpacityFixed, embeddingObsOpacityMode: cellOpacityMode, featureValueColormap: geneExpressionColormap, featureValueColormapRange: geneExpressionColormapRange, tooltipsVisible, tooltipObsSetsMode, sampleSetSelection: sampleSetSelectionFromCoordination, sampleSetColor, embeddingPointsVisible, embeddingContoursVisible, embeddingContoursFilled, embeddingContourPercentiles: contourPercentiles, contourColorEncoding, contourColor, featureAggregationStrategy, annotationStory, annotationShapes, annotationOverlayVisible, annotationSemanticZoom, annotationTransitionDuration, annotationEditable, annotationFrameIndex }, { setEmbeddingZoom: setZoom, setEmbeddingTargetX: setTargetX, setEmbeddingTargetY: setTargetY, setEmbeddingTargetZ: setTargetZ, setObsFilter: setCellFilter, setObsSetSelection: setCellSetSelection, setObsHighlight: setCellHighlight, setObsSetColor: setCellSetColor, setObsColorEncoding: setCellColorEncoding, setAdditionalObsSets: setAdditionalCellSets, setEmbeddingObsSetPolygonsVisible: setCellSetPolygonsVisible, setEmbeddingObsSetLabelsVisible: setCellSetLabelsVisible, setEmbeddingObsSetLabelSize: setCellSetLabelSize, setEmbeddingObsRadius: setCellRadiusFixed, setEmbeddingObsRadiusMode: setCellRadiusMode, setEmbeddingObsOpacity: setCellOpacityFixed, setEmbeddingObsOpacityMode: setCellOpacityMode, setFeatureValueColormap: setGeneExpressionColormap, setFeatureValueColormapRange: setGeneExpressionColormapRange, setTooltipsVisible, setEmbeddingPointsVisible, setEmbeddingContoursVisible, setEmbeddingContoursFilled, setEmbeddingContourPercentiles: setContourPercentiles, setContourColorEncoding, setFeatureAggregationStrategy, setAnnotationStory }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType$1.SCATTERPLOT], coordinationScopes, coordinationValues, viewUid);
239504
+ const annotationEditingProps = useAnnotationEditingForView(viewUid, Boolean(areAnnotationsEditable && annotationEditable && typeof annotationFrameIndex === "number"));
239463
239505
  const { embeddingZoom: initialZoom, embeddingTargetX: initialTargetX, embeddingTargetY: initialTargetY } = useInitialCoordination(COMPONENT_COORDINATION_TYPES[ViewType$1.SCATTERPLOT], coordinationScopes, coordinationValues);
239464
239506
  const observationsLabel = observationsLabelOverride || obsType;
239465
239507
  const sampleSetSelection = sampleSetSelectionFromProps || sampleSetSelectionFromCoordination;
@@ -239635,7 +239677,7 @@ function EmbeddingScatterplotSubscriber(props) {
239635
239677
  initialTargetY,
239636
239678
  averageFillDensity
239637
239679
  ]);
239638
- const getObsInfo2 = useGetObsInfo(observationsLabel, obsLabelsTypes, obsLabelsData, obsSetsMembership);
239680
+ const getObsInfo2 = useGetObsInfo(observationsLabel, obsLabelsTypes, obsLabelsData, obsSetsMembership, cellSetSelection, tooltipObsSetsMode);
239639
239681
  const allCellsSelected = !(deferredCellSetSelection && mergedCellSets);
239640
239682
  const getCellIsSelected = useCallback((object2, { index: index2 }) => allCellsSelected || obsColorIndices.colorIndices[index2] !== 0 ? 1 : 0, [allCellsSelected, obsColorIndices]);
239641
239683
  const cellRadius = cellRadiusMode === "manual" ? cellRadiusFixed : dynamicCellRadius;
@@ -239745,7 +239787,7 @@ function EmbeddingScatterplotSubscriber(props) {
239745
239787
  featureAggregationStrategyToUse,
239746
239788
  obsSetsColumns
239747
239789
  ]);
239748
- const annotationFrameCoordinationValues = getAnnotationFrameCoordinationValues(annotationStory, annotationFrameIndex, uuid2);
239790
+ const annotationFrameCoordinationValues = getAnnotationFrameCoordinationValues(annotationStory, annotationFrameIndex, viewUid);
239749
239791
  const annotationTransitionProps = useAnnotationFrameTransition({ zoom: zoom2, targetX: targetX2, targetY: targetY2 }, {
239750
239792
  zoom: annotationFrameCoordinationValues?.[CoordinationType$1.EMBEDDING_ZOOM],
239751
239793
  targetX: annotationFrameCoordinationValues?.[CoordinationType$1.EMBEDDING_TARGET_X],
@@ -239841,7 +239883,7 @@ function DualEmbeddingScatterplotSubscriber(props) {
239841
239883
  const isCaseCtrl = Array.isArray(sampleSetSelection) && sampleSetSelection.length === 2;
239842
239884
  const caseSampleSetSelection = useMemo$1(() => sampleSetSelection?.[0] ? [sampleSetSelection[0]] : null, [sampleSetSelection]);
239843
239885
  const ctrlSampleSetSelection = useMemo$1(() => sampleSetSelection?.[1] ? [sampleSetSelection[1]] : null, [sampleSetSelection]);
239844
- return jsxs("div", { style: { width: "100%", height: "100%", display: "flex", flexDirection: "row" }, children: [jsx$1("div", { style: { width: isCaseCtrl ? "50%" : "100%", display: "flex", flexDirection: "column" }, children: jsx$1(EmbeddingScatterplotSubscriber, { ...props, uuid: `${uuid2}-case`, title: isCaseCtrl ? `Scatterplot (${embeddingType}), ${caseSampleSetSelection?.[0]?.at(-1)}` : null, sampleSetSelection: caseSampleSetSelection }) }), isCaseCtrl ? jsx$1("div", { style: { width: "50%", display: "flex", flexDirection: "column" }, children: jsx$1(EmbeddingScatterplotSubscriber, { ...props, uuid: `${uuid2}-ctrl`, title: `Scatterplot (${embeddingType}), ${ctrlSampleSetSelection?.[0]?.at(-1)}`, sampleSetSelection: ctrlSampleSetSelection }) }) : null] });
239886
+ return jsxs("div", { style: { width: "100%", height: "100%", display: "flex", flexDirection: "row" }, children: [jsx$1("div", { style: { width: isCaseCtrl ? "50%" : "100%", display: "flex", flexDirection: "column" }, children: jsx$1(EmbeddingScatterplotSubscriber, { ...props, uuid: `${uuid2}-case`, viewUid: uuid2, title: isCaseCtrl ? `Scatterplot (${embeddingType}), ${caseSampleSetSelection?.[0]?.at(-1)}` : null, sampleSetSelection: caseSampleSetSelection }) }), isCaseCtrl ? jsx$1("div", { style: { width: "50%", display: "flex", flexDirection: "column" }, children: jsx$1(EmbeddingScatterplotSubscriber, { ...props, uuid: `${uuid2}-ctrl`, viewUid: uuid2, title: `Scatterplot (${embeddingType}), ${ctrlSampleSetSelection?.[0]?.at(-1)}`, sampleSetSelection: ctrlSampleSetSelection }) }) : null] });
239845
239887
  }
239846
239888
  function GatingScatterplotOptions(props) {
239847
239889
  const { featureType, gatingFeatureSelectionX, setGatingFeatureSelectionX, gatingFeatureSelectionY, setGatingFeatureSelectionY, gatingFeatureValueTransform, setGatingFeatureValueTransform, gatingFeatureValueTransformCoefficient, setGatingFeatureValueTransformCoefficient, geneSelectOptions, transformOptions } = props;
@@ -259977,7 +260019,7 @@ function SpatialSubscriber$1(props) {
259977
260019
  const setComponentHover = useSetComponentHover();
259978
260020
  const setComponentViewInfo = useSetComponentViewInfo(uuid2);
259979
260021
  useAnnotationFrameCoordination(uuid2, coordinationScopes);
259980
- const [{ dataset, obsType, featureType, featureValueType, spatialZoom: zoom2, spatialTargetX: targetX2, spatialTargetY: targetY2, spatialTargetZ: targetZ, spatialRotationX: rotationX, spatialRotationY: rotationY, spatialRotationZ: rotationZ, spatialRotationOrbit: rotationOrbit, spatialOrbitAxis: orbitAxis, spatialImageLayer: imageLayers, spatialSegmentationLayer: cellsLayer, spatialPointLayer: moleculesLayer, spatialNeighborhoodLayer: neighborhoodsLayer, obsFilter: cellFilter, obsHighlight: cellHighlight, moleculeHighlight, featureSelection: geneSelection, obsSetSelection: cellSetSelection, obsSetColor: cellSetColor, obsColorEncoding: cellColorEncoding, additionalObsSets: additionalCellSets, spatialAxisFixed, featureValueColormap: geneExpressionColormap, featureValueColormapRange: geneExpressionColormapRange, tooltipsVisible, photometricInterpretation: photometricInterpretationFromCoordination, featureAggregationStrategy, annotationStory, annotationShapes, annotationOverlayVisible, annotationSemanticZoom, annotationTransitionDuration, annotationEditable, annotationFrameIndex }, { setSpatialZoom: setZoom, setSpatialTargetX: setTargetX, setSpatialTargetY: setTargetY, setSpatialTargetZ: setTargetZ, setSpatialRotationX: setRotationX, setSpatialRotationOrbit: setRotationOrbit, setSpatialOrbitAxis: setOrbitAxis, setSpatialImageLayer: setRasterLayers, setSpatialSegmentationLayer: setCellsLayer, setSpatialPointLayer: setMoleculesLayer, setSpatialNeighborhoodLayer: setNeighborhoodsLayer, setObsFilter: setCellFilter, setObsSetSelection: setCellSetSelection, setObsHighlight: setCellHighlight, setObsSetColor: setCellSetColor, setObsColorEncoding: setCellColorEncoding, setAdditionalObsSets: setAdditionalCellSets, setMoleculeHighlight, setSpatialAxisFixed, setFeatureValueColormap: setGeneExpressionColormap, setFeatureValueColormapRange: setGeneExpressionColormapRange, setTooltipsVisible, setFeatureAggregationStrategy, setAnnotationStory }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType$1.SPATIAL], coordinationScopes);
260022
+ const [{ dataset, obsType, featureType, featureValueType, spatialZoom: zoom2, spatialTargetX: targetX2, spatialTargetY: targetY2, spatialTargetZ: targetZ, spatialRotationX: rotationX, spatialRotationY: rotationY, spatialRotationZ: rotationZ, spatialRotationOrbit: rotationOrbit, spatialOrbitAxis: orbitAxis, spatialImageLayer: imageLayers, spatialSegmentationLayer: cellsLayer, spatialPointLayer: moleculesLayer, spatialNeighborhoodLayer: neighborhoodsLayer, obsFilter: cellFilter, obsHighlight: cellHighlight, moleculeHighlight, featureSelection: geneSelection, obsSetSelection: cellSetSelection, obsSetColor: cellSetColor, obsColorEncoding: cellColorEncoding, additionalObsSets: additionalCellSets, spatialAxisFixed, featureValueColormap: geneExpressionColormap, featureValueColormapRange: geneExpressionColormapRange, tooltipsVisible, tooltipObsSetsMode, photometricInterpretation: photometricInterpretationFromCoordination, featureAggregationStrategy, annotationStory, annotationShapes, annotationOverlayVisible, annotationSemanticZoom, annotationTransitionDuration, annotationEditable, annotationFrameIndex }, { setSpatialZoom: setZoom, setSpatialTargetX: setTargetX, setSpatialTargetY: setTargetY, setSpatialTargetZ: setTargetZ, setSpatialRotationX: setRotationX, setSpatialRotationOrbit: setRotationOrbit, setSpatialOrbitAxis: setOrbitAxis, setSpatialImageLayer: setRasterLayers, setSpatialSegmentationLayer: setCellsLayer, setSpatialPointLayer: setMoleculesLayer, setSpatialNeighborhoodLayer: setNeighborhoodsLayer, setObsFilter: setCellFilter, setObsSetSelection: setCellSetSelection, setObsHighlight: setCellHighlight, setObsSetColor: setCellSetColor, setObsColorEncoding: setCellColorEncoding, setAdditionalObsSets: setAdditionalCellSets, setMoleculeHighlight, setSpatialAxisFixed, setFeatureValueColormap: setGeneExpressionColormap, setFeatureValueColormapRange: setGeneExpressionColormapRange, setTooltipsVisible, setFeatureAggregationStrategy, setAnnotationStory }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType$1.SPATIAL], coordinationScopes);
259981
260023
  const annotationEditingProps = useAnnotationEditingForView(uuid2, Boolean(areAnnotationsEditable && annotationEditable && typeof annotationFrameIndex === "number"));
259982
260024
  const { spatialZoom: initialZoom, spatialTargetX: initialTargetX, spatialTargetY: initialTargetY, spatialTargetZ: initialTargetZ } = useInitialCoordination(COMPONENT_COORDINATION_TYPES[ViewType$1.SPATIAL], coordinationScopes);
259983
260025
  const observationsLabel = observationsLabelOverride || obsType;
@@ -260146,7 +260188,7 @@ function SpatialSubscriber$1(props) {
260146
260188
  matrixObsIndex
260147
260189
  ]);
260148
260190
  const cellSelection = useMemo$1(() => Array.from(cellColors.keys()), [cellColors]);
260149
- const getObsInfo2 = useGetObsInfo(observationsLabel, obsLabelsTypes, obsLabelsData, obsSetsMembership);
260191
+ const getObsInfo2 = useGetObsInfo(observationsLabel, obsLabelsTypes, obsLabelsData, obsSetsMembership, cellSetSelection, tooltipObsSetsMode);
260150
260192
  const getTooltipObsInfo = useCallback((tooltipObsId, tooltipObsType) => {
260151
260193
  if (tooltipObsType === HOVER_MODE.MOLECULE_LAYER) {
260152
260194
  return {
@@ -261131,8 +261173,9 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
261131
261173
  const layerDefModelMatrix = image2?.obsSegmentations?.instance?.getModelMatrix();
261132
261174
  let selections;
261133
261175
  const hasChannelDimension = image2?.obsSegmentations?.instance?.hasDimC();
261176
+ const zIndex2 = image2?.obsSegmentations?.instance?.getClampedZIndex(targetZ) ?? 0;
261134
261177
  const nextLoaderSelection = channelScopes.map((cScope) => filterSelection(data2, {
261135
- z: targetZ,
261178
+ z: zIndex2,
261136
261179
  t: targetT,
261137
261180
  c: hasChannelDimension ? image2?.obsSegmentations?.instance?.getChannelIndex(channelCoordination[cScope][CoordinationType$1.SPATIAL_TARGET_C]) : void 0
261138
261181
  }));
@@ -261235,13 +261278,14 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
261235
261278
  const yMirror = new Matrix4$1().translate([0, yExtent, 0]).scale([1, -1, 1]);
261236
261279
  layerDefModelMatrix = new Matrix4$1(rawModelMatrix).multiplyRight(yMirror);
261237
261280
  }
261281
+ const zIndex2 = image2?.image?.instance?.getClampedZIndex(targetZ) ?? 0;
261238
261282
  let selections;
261239
261283
  const nextLoaderSelection = isRgb2 ? [0, 1, 2].map((targetC) => filterSelection(data2, {
261240
- z: targetZ,
261284
+ z: zIndex2,
261241
261285
  t: targetT,
261242
261286
  c: targetC
261243
261287
  })) : channelScopes.map((cScope) => filterSelection(data2, {
261244
- z: targetZ,
261288
+ z: zIndex2,
261245
261289
  t: targetT,
261246
261290
  c: image2?.image?.instance?.getChannelIndex(channelCoordination[cScope][CoordinationType$1.SPATIAL_TARGET_C])
261247
261291
  }));
@@ -261985,7 +262029,7 @@ function getXY(obsHighlight, viewInfo, obsIndex, obsLocations, useHoverInfoForTo
261985
262029
  const projectedObsCoord = viewInfo?.project(obsCoord);
261986
262030
  return [projectedObsCoord?.[0], projectedObsCoord?.[1]];
261987
262031
  }
261988
- function getObsInfo(obsSetsData, obsType, obsId) {
262032
+ function getObsInfo(obsSetsData, obsType, obsId, obsSetSelection, tooltipObsSetsMode) {
261989
262033
  let result = {
261990
262034
  [`${capitalize$3(obsType)} ID`]: obsId
261991
262035
  };
@@ -261994,7 +262038,7 @@ function getObsInfo(obsSetsData, obsType, obsId) {
261994
262038
  if (obsMembership) {
261995
262039
  result = {
261996
262040
  ...result,
261997
- ...Object.fromEntries(obsMembership.flatMap((path2) => path2.slice(1).map((pathEl, elLevel) => [
262041
+ ...Object.fromEntries(filterObsMembershipForTooltip(obsMembership, obsSetSelection, tooltipObsSetsMode).flatMap((path2) => path2.slice(1).map((pathEl, elLevel) => [
261998
262042
  `${path2[0]}${path2.length > 2 ? ` L${elLevel + 1}` : ""}`,
261999
262043
  pathEl
262000
262044
  ])))
@@ -262040,9 +262084,9 @@ function SpatialTooltipSubscriber(props) {
262040
262084
  "Pixel Value": JSON.stringify(pixelHighlight)
262041
262085
  }, x: projectedHoverCoord?.[0], y: projectedHoverCoord?.[1] + (yOffset += 30), featureType, featureLabelsMap }, layerScope) : null;
262042
262086
  }), segmentationLayerScopes?.flatMap((layerScope) => segmentationChannelScopesByLayer?.[layerScope]?.map((channelScope) => {
262043
- const { obsType, obsHighlight, tooltipsVisible, tooltipCrosshairsVisible, spatialChannelVisible } = segmentationChannelCoordination?.[0]?.[layerScope]?.[channelScope] || {};
262087
+ const { obsType, obsHighlight, tooltipsVisible, tooltipCrosshairsVisible, spatialChannelVisible, obsSetSelection, tooltipObsSetsMode } = segmentationChannelCoordination?.[0]?.[layerScope]?.[channelScope] || {};
262044
262088
  const obsSetsData = obsSegmentationsSetsData?.[layerScope]?.[channelScope];
262045
- const obsInfo = getObsInfo(obsSetsData, obsType, obsHighlight);
262089
+ const obsInfo = getObsInfo(obsSetsData, obsType, obsHighlight, obsSetSelection, tooltipObsSetsMode);
262046
262090
  if (!obsHighlight || !spatialChannelVisible || !tooltipsVisible && !tooltipCrosshairsVisible)
262047
262091
  return null;
262048
262092
  const { obsIndex, obsLocations } = obsSegmentationsLocations?.[layerScope]?.[channelScope] || {};
@@ -262099,12 +262143,12 @@ class ErrorBoundary extends React__default.Component {
262099
262143
  }
262100
262144
  }
262101
262145
  const LazySpatialThree = React__default.lazy(async () => {
262102
- const { SpatialWrapper: SpatialWrapper2 } = await import("./index-BpNOtGFe.js").then((n3) => n3.a);
262146
+ const { SpatialWrapper: SpatialWrapper2 } = await import("./index-Vg2it-xm.js").then((n3) => n3.a);
262103
262147
  return { default: SpatialWrapper2 };
262104
262148
  });
262105
262149
  const SpatialThreeAdapter = React__default.forwardRef((props, ref2) => jsx$1("div", { ref: ref2, style: { width: "100%", height: "100%" }, children: jsx$1(ErrorBoundary, { fallback: jsx$1("div", { children: "3D spatial view is not available in this environment." }), children: jsx$1(Suspense, { fallback: jsx$1("div", { children: "Loading..." }), children: jsx$1(LazySpatialThree, { ...props }) }) }) }));
262106
262150
  const LazySpatialAccelerated = React__default.lazy(async () => {
262107
- const { SpatialWrapper: SpatialWrapper2 } = await import("./index-b1x98NVi.js");
262151
+ const { SpatialWrapper: SpatialWrapper2 } = await import("./index-CZ9S9EsT.js");
262108
262152
  return { default: SpatialWrapper2 };
262109
262153
  });
262110
262154
  const SpatialAcceleratedAdapter = React__default.forwardRef((props, ref2) => jsx$1("div", { ref: ref2, style: { width: "100%", height: "100%" }, children: jsx$1(ErrorBoundary, { fallback: jsx$1("div", { children: "3D spatial view is not available in this environment." }), children: jsx$1(Suspense, { fallback: jsx$1("div", { children: "Loading..." }), children: jsx$1(LazySpatialAccelerated, { ...props }) }) }) }));
@@ -262361,7 +262405,7 @@ function SpatialSubscriber(props) {
262361
262405
  }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType$1.SPATIAL_BETA], coordinationScopes);
262362
262406
  const annotationEditingProps = useAnnotationEditingForView(uuid2, Boolean(areAnnotationsEditable && annotationEditable && typeof annotationFrameIndex === "number"));
262363
262407
  const { spatialZoom: initialZoom, spatialTargetX: initialTargetX, spatialTargetY: initialTargetY, spatialTargetZ: initialTargetZ } = useInitialCoordination(COMPONENT_COORDINATION_TYPES[ViewType$1.SPATIAL_BETA], coordinationScopes);
262364
- const hasSpatialCameraSnapshot = Boolean(spatialCameraSnapshot);
262408
+ const hasSpatialCameraSnapshot = Boolean(spatialCameraSnapshot) && spatialRenderingMode === "3D";
262365
262409
  const [segmentationLayerScopes, segmentationChannelScopesByLayer] = useMultiCoordinationScopesSecondaryNonNull(CoordinationType$1.SEGMENTATION_CHANNEL, CoordinationType$1.SEGMENTATION_LAYER, coordinationScopes, coordinationScopesBy);
262366
262410
  const [imageLayerScopes, imageChannelScopesByLayer] = useMultiCoordinationScopesSecondaryNonNull(CoordinationType$1.IMAGE_CHANNEL, CoordinationType$1.IMAGE_LAYER, coordinationScopes, coordinationScopesBy);
262367
262411
  const spotLayerScopes = useMultiCoordinationScopesNonNull(CoordinationType$1.SPOT_LAYER, coordinationScopes);
@@ -262391,6 +262435,7 @@ function SpatialSubscriber(props) {
262391
262435
  CoordinationType$1.OBS_HIGHLIGHT,
262392
262436
  CoordinationType$1.TOOLTIPS_VISIBLE,
262393
262437
  CoordinationType$1.TOOLTIP_CROSSHAIRS_VISIBLE,
262438
+ CoordinationType$1.TOOLTIP_OBS_SETS_MODE,
262394
262439
  CoordinationType$1.LEGEND_VISIBLE
262395
262440
  ], coordinationScopes, coordinationScopesBy, CoordinationType$1.SEGMENTATION_LAYER, CoordinationType$1.SEGMENTATION_CHANNEL);
262396
262441
  const imageLayerCoordination = useComplexCoordination([
@@ -262588,6 +262633,28 @@ function SpatialSubscriber(props) {
262588
262633
  segmentationChannelScopesByLayer
262589
262634
  ]
262590
262635
  );
262636
+ const sceneMetersPerUnit = useMemo$1(() => {
262637
+ const firstLayer = Object.values(imageData ?? {})[0];
262638
+ return firstLayer?.image?.instance?.getSceneMetersPerUnit() ?? null;
262639
+ }, [imageData]);
262640
+ const sceneCameraSnapshot = useMemo$1(() => {
262641
+ if (!spatialCameraSnapshot)
262642
+ return null;
262643
+ const inMpu = spatialCameraSnapshot.metersPerUnit;
262644
+ if (!sceneMetersPerUnit || !inMpu || inMpu === sceneMetersPerUnit) {
262645
+ return spatialCameraSnapshot;
262646
+ }
262647
+ const k = inMpu / sceneMetersPerUnit;
262648
+ return {
262649
+ ...spatialCameraSnapshot,
262650
+ position: spatialCameraSnapshot.position.map((p) => p * k),
262651
+ projectionScale: spatialCameraSnapshot.projectionScale * k,
262652
+ metersPerUnit: sceneMetersPerUnit
262653
+ };
262654
+ }, [spatialCameraSnapshot, sceneMetersPerUnit]);
262655
+ const setSceneCameraSnapshot = useCallback((snapshot) => {
262656
+ setSpatialCameraSnapshot({ ...snapshot, metersPerUnit: sceneMetersPerUnit });
262657
+ }, [setSpatialCameraSnapshot, sceneMetersPerUnit]);
262591
262658
  useEffect(() => {
262592
262659
  if (width2 && height2) {
262593
262660
  if (typeof initialTargetX !== "number" || typeof initialTargetY !== "number") {
@@ -262622,6 +262689,10 @@ function SpatialSubscriber(props) {
262622
262689
  if (prevIs3dMode.current === is3dMode) {
262623
262690
  return;
262624
262691
  }
262692
+ if (hasSpatialCameraSnapshot) {
262693
+ prevIs3dMode.current = is3dMode;
262694
+ return;
262695
+ }
262625
262696
  if (typeof defaultTargetX !== "number" || typeof defaultTargetY !== "number") {
262626
262697
  return;
262627
262698
  }
@@ -262632,7 +262703,14 @@ function SpatialSubscriber(props) {
262632
262703
  setZoom(defaultZoom);
262633
262704
  setRotationX(is3dMode ? 0 : null);
262634
262705
  setRotationOrbit(is3dMode ? 0 : null);
262635
- }, [is3dMode, defaultTargetX, defaultTargetY, defaultTargetZ, defaultZoom]);
262706
+ }, [
262707
+ is3dMode,
262708
+ hasSpatialCameraSnapshot,
262709
+ defaultTargetX,
262710
+ defaultTargetY,
262711
+ defaultTargetZ,
262712
+ defaultZoom
262713
+ ]);
262636
262714
  const annotationFrameCoordinationValues = getAnnotationFrameCoordinationValues(annotationStory, annotationFrameIndex, uuid2);
262637
262715
  const annotationTransitionProps = useAnnotationFrameTransition(
262638
262716
  { zoom: zoom2, targetX: targetX2, targetY: targetY2 },
@@ -262813,7 +262891,7 @@ function SpatialSubscriber(props) {
262813
262891
  rotationX,
262814
262892
  rotationOrbit,
262815
262893
  ...annotationTransitionProps
262816
- } : DEFAULT_VIEW_STATE, orbitAxis, spatialAxisFixed, setViewState: isValidViewState ? setViewState : SET_VIEW_STATE_NOOP, originalViewState, spatialRenderingMode, updateViewInfo: setComponentViewInfo, delegateHover, obsPoints: obsPointsData, pointLayerScopes, pointLayerCoordination, pointMultiObsLabels: pointMultiObsLabelsData, pointMatrixIndices: pointMultiIndicesData, obsSpots: obsSpotsData, spotLayerScopes, spotLayerCoordination, obsSpotsSets: obsSpotsSetsData, spotMatrixIndices: spotMultiIndicesData, spotMultiExpressionData: spotMultiExpressionNormDataAggregated || spotMultiExpressionNormData, segmentationLayerScopes, segmentationLayerCoordination, segmentationChannelScopesByLayer, segmentationChannelCoordination, obsSegmentations: obsSegmentationsData, obsSegmentationsLocations: obsSegmentationsLocationsData, obsSegmentationsSets: obsSegmentationsSetsData, segmentationMatrixIndices: segmentationMultiIndicesData, segmentationMultiExpressionData: segmentationMultiExpressionNormDataAggregated || segmentationMultiExpressionNormData, bitmaskValueIsIndex, images: imageData, imageLayerScopes, imageLayerCoordination, imageChannelScopesByLayer, imageChannelCoordination, setTiledPointsLoadingProgress, spatialCameraSnapshot: hasSpatialCameraSnapshot ? spatialCameraSnapshot : null, setSpatialCameraSnapshot: hasSpatialCameraSnapshot ? setSpatialCameraSnapshot : null, annotationShapes, annotationOverlayVisible, annotationSemanticZoom, hideRecenter: hasSpatialCameraSnapshot, ...annotationEditingProps }), !disableTooltip && jsx$1(SpatialTooltipSubscriber, {
262894
+ } : DEFAULT_VIEW_STATE, orbitAxis, spatialAxisFixed, setViewState: isValidViewState ? setViewState : SET_VIEW_STATE_NOOP, originalViewState, spatialRenderingMode, updateViewInfo: setComponentViewInfo, delegateHover, obsPoints: obsPointsData, pointLayerScopes, pointLayerCoordination, pointMultiObsLabels: pointMultiObsLabelsData, pointMatrixIndices: pointMultiIndicesData, obsSpots: obsSpotsData, spotLayerScopes, spotLayerCoordination, obsSpotsSets: obsSpotsSetsData, spotMatrixIndices: spotMultiIndicesData, spotMultiExpressionData: spotMultiExpressionNormDataAggregated || spotMultiExpressionNormData, segmentationLayerScopes, segmentationLayerCoordination, segmentationChannelScopesByLayer, segmentationChannelCoordination, obsSegmentations: obsSegmentationsData, obsSegmentationsLocations: obsSegmentationsLocationsData, obsSegmentationsSets: obsSegmentationsSetsData, segmentationMatrixIndices: segmentationMultiIndicesData, segmentationMultiExpressionData: segmentationMultiExpressionNormDataAggregated || segmentationMultiExpressionNormData, bitmaskValueIsIndex, images: imageData, imageLayerScopes, imageLayerCoordination, imageChannelScopesByLayer, imageChannelCoordination, setTiledPointsLoadingProgress, spatialCameraSnapshot: hasSpatialCameraSnapshot ? sceneCameraSnapshot : null, setSpatialCameraSnapshot: hasSpatialCameraSnapshot ? setSceneCameraSnapshot : null, annotationShapes, annotationOverlayVisible, annotationSemanticZoom, hideRecenter: hasSpatialCameraSnapshot, ...annotationEditingProps }), !disableTooltip && jsx$1(SpatialTooltipSubscriber, {
262817
262895
  parentUuid: uuid2,
262818
262896
  width: width2,
262819
262897
  height: height2,
@@ -263710,7 +263788,7 @@ function HeatmapSubscriber(props) {
263710
263788
  const coordinationScopes = useCoordinationScopes(coordinationScopesRaw);
263711
263789
  const setComponentHover = useSetComponentHover();
263712
263790
  const setComponentViewInfo = useSetComponentViewInfo(uuid2);
263713
- const [{ dataset, obsType, featureType, featureValueType, heatmapZoomX: zoomX, heatmapTargetX: targetX2, heatmapTargetY: targetY2, featureSelection: geneSelection, obsHighlight: cellHighlight, featureHighlight: geneHighlight, obsSetSelection: cellSetSelection, obsSetColor: cellSetColor, additionalObsSets: additionalCellSets, featureValueColormap: geneExpressionColormap, featureValueColormapRange: geneExpressionColormapRange, tooltipsVisible }, { setHeatmapZoomX: setZoomX, setHeatmapZoomY: setZoomY, setHeatmapTargetX: setTargetX, setHeatmapTargetY: setTargetY, setObsHighlight: setCellHighlight, setFeatureSelection: setGeneSelection, setObsColorEncoding: setCellColorEncoding, setFeatureHighlight: setGeneHighlight, setObsSetSelection: setCellSetSelection, setObsSetColor: setCellSetColor, setFeatureValueColormapRange: setGeneExpressionColormapRange, setFeatureValueColormap: setGeneExpressionColormap, setTooltipsVisible }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType$1.HEATMAP], coordinationScopes);
263791
+ const [{ dataset, obsType, featureType, featureValueType, heatmapZoomX: zoomX, heatmapTargetX: targetX2, heatmapTargetY: targetY2, featureSelection: geneSelection, obsHighlight: cellHighlight, featureHighlight: geneHighlight, obsSetSelection: cellSetSelection, obsSetColor: cellSetColor, additionalObsSets: additionalCellSets, featureValueColormap: geneExpressionColormap, featureValueColormapRange: geneExpressionColormapRange, tooltipsVisible, tooltipObsSetsMode }, { setHeatmapZoomX: setZoomX, setHeatmapZoomY: setZoomY, setHeatmapTargetX: setTargetX, setHeatmapTargetY: setTargetY, setObsHighlight: setCellHighlight, setFeatureSelection: setGeneSelection, setObsColorEncoding: setCellColorEncoding, setFeatureHighlight: setGeneHighlight, setObsSetSelection: setCellSetSelection, setObsSetColor: setCellSetColor, setFeatureValueColormapRange: setGeneExpressionColormapRange, setFeatureValueColormap: setGeneExpressionColormap, setTooltipsVisible }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType$1.HEATMAP], coordinationScopes);
263714
263792
  const observationsLabel = observationsLabelOverride || obsType;
263715
263793
  const observationsPluralLabel = pluralize(observationsLabel);
263716
263794
  const variablesLabel = variablesLabelOverride || featureType;
@@ -263764,7 +263842,7 @@ function HeatmapSubscriber(props) {
263764
263842
  cellSetSelection,
263765
263843
  obsIndex
263766
263844
  ]);
263767
- const getObsInfo2 = useGetObsInfo(observationsLabel, obsLabelsTypes, obsLabelsData, obsSetsMembership);
263845
+ const getObsInfo2 = useGetObsInfo(observationsLabel, obsLabelsTypes, obsLabelsData, obsSetsMembership, cellSetSelection, tooltipObsSetsMode);
263768
263846
  const getObsMembership = useGetObsMembership(obsSetsMembership);
263769
263847
  const getFeatureInfo = useCallback((featureId2) => {
263770
263848
  if (featureId2) {
@@ -273464,7 +273542,7 @@ function ImageChannelController(props) {
273464
273542
  const selection = {
273465
273543
  t: ctx.queryKey[2],
273466
273544
  c: ctx.queryKey[3],
273467
- z: Math.floor(ctx.queryKey[4])
273545
+ z: ctx.meta.image?.getClampedZIndex(ctx.queryKey[4]) ?? 0
273468
273546
  };
273469
273547
  const stats = await getMultiSelectionStats({
273470
273548
  loader: loader2,
@@ -275579,6 +275657,10 @@ function getExistingScope(layout, coordinationType) {
275579
275657
  const scope = layout.map((view) => view.coordinationScopes?.[coordinationType]).find((s2) => typeof s2 === "string");
275580
275658
  return scope;
275581
275659
  }
275660
+ function getMaxColumnHeight(layout) {
275661
+ const bottoms = layout.map((view) => view.y + view.h).filter((bottom2) => Number.isFinite(bottom2) && bottom2 >= 1);
275662
+ return bottoms.length > 0 ? Math.max(...bottoms) : NUM_GRID_ROWS;
275663
+ }
275582
275664
  function addAnnotationControllerView(config3, options = {}) {
275583
275665
  const { width: width2 = DEFAULT_ANNOTATION_CONTROLLER_WIDTH, uid: uid2 = DEFAULT_ANNOTATION_CONTROLLER_UID, closeButtonVisible } = options;
275584
275666
  if (!Number.isInteger(width2) || width2 < 1 || width2 >= NUM_GRID_COLUMNS) {
@@ -275609,13 +275691,49 @@ function addAnnotationControllerView(config3, options = {}) {
275609
275691
  x: remainingColumns,
275610
275692
  y: 0,
275611
275693
  w: width2,
275612
- h: NUM_GRID_ROWS
275694
+ h: getMaxColumnHeight(layout)
275613
275695
  });
275614
275696
  return {
275615
275697
  ...config3,
275616
275698
  layout: newLayout
275617
275699
  };
275618
275700
  }
275701
+ function removeAnnotationControllerView(config3) {
275702
+ const layout = (config3?.layout || []).filter((view) => view.component !== ViewType$1.ANNOTATION_CONTROLLER);
275703
+ const clampX = (value2) => Math.min(Math.max(value2, 0), NUM_GRID_COLUMNS);
275704
+ const isColumnOccupied = Array.from({ length: NUM_GRID_COLUMNS }, (_, col) => layout.some((view) => clampX(view.x) <= col && col < clampX(view.x + view.w)));
275705
+ const numOccupiedColumns = isColumnOccupied.filter(Boolean).length;
275706
+ if (numOccupiedColumns === 0) {
275707
+ return {
275708
+ ...config3,
275709
+ layout
275710
+ };
275711
+ }
275712
+ const scaleX2 = (value2) => {
275713
+ const edge = clampX(value2);
275714
+ const numOccupiedBefore = isColumnOccupied.filter((isOccupied, col) => isOccupied && col < edge).length;
275715
+ return Math.round(numOccupiedBefore * NUM_GRID_COLUMNS / numOccupiedColumns);
275716
+ };
275717
+ const newLayout = layout.map((view) => {
275718
+ const x2 = Math.min(scaleX2(view.x), NUM_GRID_COLUMNS - 1);
275719
+ const right2 = Math.min(Math.max(scaleX2(view.x + view.w), x2 + 1), NUM_GRID_COLUMNS);
275720
+ return {
275721
+ ...view,
275722
+ x: x2,
275723
+ w: right2 - x2
275724
+ };
275725
+ });
275726
+ return {
275727
+ ...config3,
275728
+ layout: newLayout
275729
+ };
275730
+ }
275731
+ function hasAnyAnnotationStory(config3) {
275732
+ const type2 = CoordinationType$1.ANNOTATION_STORY;
275733
+ const scopeValues = Object.values(config3?.coordinationSpace?.[type2] || {});
275734
+ const viewValues = (config3?.layout || []).map((view) => view.coordinationValues?.[type2]);
275735
+ return [...scopeValues, ...viewValues].some((value2) => Array.isArray(value2?.frames) && value2.frames.length > 0);
275736
+ }
275619
275737
  function isAnyAnnotationEditing(config3) {
275620
275738
  const type2 = CoordinationType$1.ANNOTATION_EDITABLE;
275621
275739
  const scopeValues = Object.values(config3?.coordinationSpace?.[type2] || {});
@@ -277495,7 +277613,7 @@ function HiglassGlobalStyles(props) {
277495
277613
  }
277496
277614
  register({ dataFetcher: ZarrMultivecDataFetcher_default, config: ZarrMultivecDataFetcher_default.config }, { pluginType: "dataFetcher" });
277497
277615
  const LazyHiGlassComponent = React__default.lazy(async () => {
277498
- const { HiGlassComponent } = await import("./higlass-R6f4spnl.js");
277616
+ const { HiGlassComponent } = await import("./higlass-CJExboBo.js");
277499
277617
  return { default: HiGlassComponent };
277500
277618
  });
277501
277619
  const HG_SIZE = 800;
@@ -280450,7 +280568,7 @@ function NeuroglancerGlobalStyles(props) {
280450
280568
  const { classes: classes2 } = props;
280451
280569
  return jsxs(Fragment, { children: [jsx$1(GlobalStyles$3, { styles: globalNeuroglancerCss }), jsx$1(ScopedGlobalStyles, { styles: globalNeuroglancerStyles, parentClassName: classes2.neuroglancerWrapper })] });
280452
280570
  }
280453
- const LazyReactNeuroglancer = React__default.lazy(() => import("./ReactNeuroglancer-CGw5kiSQ.js"));
280571
+ const LazyReactNeuroglancer = React__default.lazy(() => import("./ReactNeuroglancer-Db7O0CnI.js"));
280454
280572
  function createWorker() {
280455
280573
  const worker = new WorkerFactory$1();
280456
280574
  worker.AsyncComputationWorker = WorkerFactory;
@@ -280548,9 +280666,9 @@ class NeuroglancerComp extends PureComponent {
280548
280666
  this.bundleRoot = null;
280549
280667
  }
280550
280668
  render() {
280551
- const { classes: classes2, viewerState, cellColorMapping, onLayerLoadingChange, onAnnotationSourceReady, onViewerReady, meshOpacity } = this.props;
280669
+ const { classes: classes2, viewerState, cellColorMapping, onLayerLoadingChange, onAnnotationSourceReady, onViewerReady, meshOpacity, allowEmptySegments } = this.props;
280552
280670
  const { bundleRootReady } = this.state;
280553
- return jsxs(Fragment, { children: [jsx$1(NeuroglancerGlobalStyles, { classes: classes2 }), jsx$1("div", { className: classes2.neuroglancerWrapper, children: jsx$1(Suspense, { fallback: jsx$1("div", { children: "Loading..." }), children: bundleRootReady && jsx$1(LazyReactNeuroglancer, { brainMapsClientId: "NOT_A_VALID_ID", viewerState, onViewerStateChanged: this.onViewerStateChanged, onLayerLoadingChange, bundleRoot: this.bundleRoot, cellColorMapping, ref: this.onRef, onAnnotationSourceReady, onViewerReady, meshOpacity }) }) })] });
280671
+ return jsxs(Fragment, { children: [jsx$1(NeuroglancerGlobalStyles, { classes: classes2 }), jsx$1("div", { className: classes2.neuroglancerWrapper, children: jsx$1(Suspense, { fallback: jsx$1("div", { children: "Loading..." }), children: bundleRootReady && jsx$1(LazyReactNeuroglancer, { brainMapsClientId: "NOT_A_VALID_ID", viewerState, onViewerStateChanged: this.onViewerStateChanged, onLayerLoadingChange, bundleRoot: this.bundleRoot, cellColorMapping, ref: this.onRef, onAnnotationSourceReady, onViewerReady, meshOpacity, allowEmptySegments }) }) })] });
280554
280672
  }
280555
280673
  }
280556
280674
  function customIsEqualForCellColors(prevDeps, nextDeps) {
@@ -281326,6 +281444,13 @@ function useNeuroglancerViewerState(theme, showAxisLines, segmentationLayerScope
281326
281444
  return viewerState;
281327
281445
  }
281328
281446
  const ANNOTATION_HEADER_OFFSET = 8;
281447
+ function ngMetersPerUnit(dimensions) {
281448
+ if (!dimensions?.x)
281449
+ return null;
281450
+ const [scale2, unit2] = dimensions.x;
281451
+ const factor = UNIT_TO_METERS[unit2];
281452
+ return factor ? scale2 * factor : null;
281453
+ }
281329
281454
  const GREY_HEX = "#323232";
281330
281455
  const EPSILON_KEYS_MAPPING_NG = {
281331
281456
  projectionScale: 5,
@@ -281481,7 +281606,14 @@ function NeuroglancerSubscriber(props) {
281481
281606
  // the existing spatialZoom, spatialTargetX, spatialRotationOrbit, etc,
281482
281607
  // and then NeuroglancerSubscriber should internally convert
281483
281608
  // to NG-compatible values, which would eliminate the need for this.
281484
- initialNgCameraState
281609
+ initialNgCameraState,
281610
+ // Detail mode: render only the meshes selected (obsSets) or hovered
281611
+ // (obsHighlight) elsewhere, with an independent camera.
281612
+ detailMode = false,
281613
+ detailUseSelection = false,
281614
+ // >1: this view shows the shared camera N× more zoomed in.
281615
+ // Pan/rotation are shared via spatialCameraSnapshot; zoom keeps a fixed ratio.
281616
+ cameraZoomFactor = 1
281485
281617
  } = props;
281486
281618
  const loaders = useLoaders();
281487
281619
  const mergeCoordination = useMergeCoordination();
@@ -281524,7 +281656,8 @@ function NeuroglancerSubscriber(props) {
281524
281656
  obsSetSelection: cellSetSelection,
281525
281657
  additionalObsSets: additionalCellSets,
281526
281658
  obsHighlight: cellHighlight,
281527
- spatialCameraSnapshot
281659
+ spatialCameraSnapshot,
281660
+ spatialRenderingMode
281528
281661
  }, { setSpatialCameraSnapshot, setAdditionalObsSets: setAdditionalCellSets, setObsSetColor: setCellSetColor, setObsColorEncoding: setCellColorEncoding, setObsSetSelection: setCellSetSelection, setObsHighlight: setCellHighlight }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType$1.NEUROGLANCER], coordinationScopes);
281529
281662
  const csvUrlRef = useRef(null);
281530
281663
  const csvUrl = useMemo$1(() => {
@@ -281681,15 +281814,27 @@ function NeuroglancerSubscriber(props) {
281681
281814
  });
281682
281815
  const lastSeenCameraSnapshotRef = useRef(null);
281683
281816
  const spatialBetaJustPushedRef = useRef(false);
281817
+ const is3dMode = spatialRenderingMode === "3D";
281818
+ const hasSpatialCameraSnapshot = Boolean(spatialCameraSnapshot) && is3dMode;
281684
281819
  useEffect(() => {
281685
- if (!spatialCameraSnapshot)
281820
+ if (detailMode)
281821
+ return;
281822
+ if (!hasSpatialCameraSnapshot)
281686
281823
  return;
281687
281824
  if (spatialCameraSnapshot === lastSeenCameraSnapshotRef.current)
281688
281825
  return;
281689
281826
  lastSeenCameraSnapshotRef.current = spatialCameraSnapshot;
281690
- const { position: position2, quaternion: quaternion2, projectionScale } = spatialCameraSnapshot;
281827
+ const { quaternion: quaternion2 } = spatialCameraSnapshot;
281828
+ let { position: position2, projectionScale } = spatialCameraSnapshot;
281691
281829
  if (!Array.isArray(position2) || !Array.isArray(quaternion2))
281692
281830
  return;
281831
+ const ownMpu = ngMetersPerUnit(latestViewerStateRef.current?.dimensions);
281832
+ const inMpu = spatialCameraSnapshot.metersPerUnit;
281833
+ if (ownMpu && inMpu && ownMpu !== inMpu) {
281834
+ const k = inMpu / ownMpu;
281835
+ position2 = position2.map((p) => p * k);
281836
+ projectionScale *= k;
281837
+ }
281693
281838
  const unflipped = multiplyQuat(quaternion2, Q_Y_UP);
281694
281839
  lastInteractionSource.current = LAST_INTERACTION_SOURCE.vitessce;
281695
281840
  spatialBetaJustPushedRef.current = true;
@@ -281697,10 +281842,10 @@ function NeuroglancerSubscriber(props) {
281697
281842
  ...latestViewerStateRef.current,
281698
281843
  position: position2,
281699
281844
  projectionOrientation: unflipped,
281700
- projectionScale
281845
+ projectionScale: Number.isFinite(projectionScale) ? projectionScale / cameraZoomFactor : latestViewerStateRef.current.projectionScale
281701
281846
  };
281702
281847
  incrementLatestViewerStateIteration();
281703
- }, [spatialCameraSnapshot]);
281848
+ }, [spatialCameraSnapshot, hasSpatialCameraSnapshot, detailMode, cameraZoomFactor]);
281704
281849
  const segmentationColorMapping = useMemoCustomComparison(() => {
281705
281850
  const result = {};
281706
281851
  segmentationLayerScopes?.forEach((layerScope) => {
@@ -281897,6 +282042,8 @@ function NeuroglancerSubscriber(props) {
281897
282042
  }
281898
282043
  }, []);
281899
282044
  const updateVisibleSegments = useCallback(async () => {
282045
+ if (detailMode)
282046
+ return;
281900
282047
  if (!annotationInfoRef.current)
281901
282048
  return;
281902
282049
  if (!annotationTransformRef.current)
@@ -282019,7 +282166,7 @@ function NeuroglancerSubscriber(props) {
282019
282166
  console.warn("[updateVisibleSegments] error:", e3);
282020
282167
  setIsMeshLoading(false);
282021
282168
  }
282022
- }, [segmentationLayerScopes, pointLayerScopes, meshLoadProjectionScaleThreshold]);
282169
+ }, [segmentationLayerScopes, pointLayerScopes, meshLoadProjectionScaleThreshold, detailMode]);
282023
282170
  useEffect(() => {
282024
282171
  updateVisibleSegmentsThrottledRef.current = throttle$1(updateVisibleSegments, 500);
282025
282172
  return () => updateVisibleSegmentsThrottledRef.current?.cancel();
@@ -282037,7 +282184,7 @@ function NeuroglancerSubscriber(props) {
282037
282184
  incrementLatestViewerStateIteration();
282038
282185
  }, [initialViewerState]);
282039
282186
  const hasMatchingAnnotationSource = useMemo$1(() => {
282040
- if (!cellsUrl)
282187
+ if (detailMode || !cellsUrl)
282041
282188
  return false;
282042
282189
  const firstPointScope = pointLayerScopes?.[0];
282043
282190
  return pointsHaveMatchingSegmentation({
@@ -282046,7 +282193,7 @@ function NeuroglancerSubscriber(props) {
282046
282193
  segmentationChannelScopesByLayer,
282047
282194
  segmentationChannelCoordination
282048
282195
  });
282049
- }, [cellsUrl, pointLayerScopes, segmentationLayerScopes, segmentationChannelScopesByLayer]);
282196
+ }, [cellsUrl, pointLayerScopes, segmentationLayerScopes, segmentationChannelScopesByLayer, detailMode]);
282050
282197
  useEffect(() => {
282051
282198
  if (!cellsUrl || !annotationInfo)
282052
282199
  return;
@@ -282071,13 +282218,14 @@ function NeuroglancerSubscriber(props) {
282071
282218
  const handleStateUpdate = useCallback((newState) => {
282072
282219
  lastInteractionSource.current = LAST_INTERACTION_SOURCE.neuroglancer;
282073
282220
  const { projectionScale, projectionOrientation, position: position2 } = newState;
282074
- if (Array.isArray(position2) && Array.isArray(projectionOrientation)) {
282221
+ if (!detailMode && Array.isArray(position2) && Array.isArray(projectionOrientation)) {
282075
282222
  const flippedQuaternion = multiplyQuat(projectionOrientation, Q_Y_UP);
282076
282223
  const snapshot = {
282077
282224
  position: Array.from(position2),
282078
282225
  quaternion: Array.from(flippedQuaternion),
282079
- projectionScale,
282080
- fovDegrees: 45
282226
+ projectionScale: Number.isFinite(projectionScale) ? projectionScale * cameraZoomFactor : latestViewerStateRef.current?.projectionScale,
282227
+ fovDegrees: 45,
282228
+ metersPerUnit: ngMetersPerUnit(latestViewerStateRef.current?.dimensions)
282081
282229
  };
282082
282230
  lastSeenCameraSnapshotRef.current = snapshot;
282083
282231
  setSpatialCameraSnapshot(snapshot);
@@ -282088,8 +282236,9 @@ function NeuroglancerSubscriber(props) {
282088
282236
  projectionScale,
282089
282237
  position: position2
282090
282238
  };
282091
- updateVisibleSegmentsThrottledRef.current?.();
282092
- }, [setSpatialCameraSnapshot]);
282239
+ if (!detailMode)
282240
+ updateVisibleSegmentsThrottledRef.current?.();
282241
+ }, [setSpatialCameraSnapshot, detailMode, cameraZoomFactor]);
282093
282242
  const onSegmentClick = useCallback((value2) => {
282094
282243
  if (value2) {
282095
282244
  const id2 = String(value2);
@@ -282125,6 +282274,52 @@ function NeuroglancerSubscriber(props) {
282125
282274
  setIsLayersLoaded(true);
282126
282275
  }
282127
282276
  }, [hasMatchingAnnotationSource, isReady, segmentationLayerScopes]);
282277
+ const lastHoveredIdRef = useRef(null);
282278
+ if (detailMode && cellHighlight != null) {
282279
+ lastHoveredIdRef.current = String(cellHighlight);
282280
+ }
282281
+ const detailSegmentIds = useMemo$1(() => {
282282
+ if (!detailMode)
282283
+ return null;
282284
+ const layerScope = segmentationLayerScopes?.[0];
282285
+ const channelScope = segmentationChannelScopesByLayer?.[layerScope]?.[0];
282286
+ if (!layerScope || !channelScope)
282287
+ return [];
282288
+ const channel = segmentationChannelCoordination?.[0]?.[layerScope]?.[channelScope] ?? {};
282289
+ const selection = channel.obsSetSelection ?? cellSetSelection;
282290
+ const extraSets = channel.additionalObsSets ?? additionalCellSets;
282291
+ const layerSets = obsSegmentationsSetsData?.[layerScope]?.[channelScope]?.obsSets;
282292
+ const toMeshId = (id2) => {
282293
+ const stripped = String(id2).replace(/^.*_/, "");
282294
+ return String(cellIdToMeshIdRef.current?.[stripped] ?? stripped);
282295
+ };
282296
+ const ids = /* @__PURE__ */ new Set();
282297
+ if (detailUseSelection && selection?.length && (layerSets || extraSets)) {
282298
+ const merged = mergeObsSets(layerSets, extraSets);
282299
+ selection.forEach((setPath) => {
282300
+ let node2 = { children: merged?.tree };
282301
+ setPath.forEach((name2) => {
282302
+ node2 = node2?.children?.find((n3) => n3.name === name2);
282303
+ });
282304
+ node2?.set?.forEach(([id2]) => ids.add(toMeshId(id2)));
282305
+ });
282306
+ }
282307
+ if (lastHoveredIdRef.current != null) {
282308
+ ids.add(toMeshId(lastHoveredIdRef.current));
282309
+ }
282310
+ return [...ids].sort();
282311
+ }, [
282312
+ detailMode,
282313
+ detailUseSelection,
282314
+ segmentationLayerScopes,
282315
+ segmentationChannelScopesByLayer,
282316
+ segmentationChannelCoordination,
282317
+ cellSetSelection,
282318
+ additionalCellSets,
282319
+ obsSegmentationsSetsData,
282320
+ cellHighlight,
282321
+ csvLoaded
282322
+ ]);
282128
282323
  const meshOpacity = hasMatchingAnnotationSource ? MESH_OPACITY : void 0;
282129
282324
  const derivedViewerState = useMemo$1(() => {
282130
282325
  const { current: current2 } = latestViewerStateRef;
@@ -282147,10 +282342,31 @@ function NeuroglancerSubscriber(props) {
282147
282342
  if (current2.layers.length <= 0) {
282148
282343
  return current2;
282149
282344
  }
282345
+ if (detailMode) {
282346
+ const ids = detailSegmentIds ?? [];
282347
+ const detailLayers = current2.layers.filter((layer) => layer.type === "segmentation").map((layer) => {
282348
+ const layerScope = segmentationLayerScopes?.find((scope) => layer.name?.includes(scope));
282349
+ const colors2 = cellColorMappingByLayer?.[layerScope]?.colors ?? {};
282350
+ const fallback2 = cellColorMappingByLayer?.[layerScope]?.defaultColor ?? GREY_HEX;
282351
+ const segmentColors = {};
282352
+ ids.forEach((id2) => {
282353
+ segmentColors[id2] = colors2[id2] || fallback2;
282354
+ });
282355
+ return {
282356
+ ...layer,
282357
+ segments: ids,
282358
+ segmentColors,
282359
+ objectAlpha: 1
282360
+ };
282361
+ });
282362
+ const updated2 = isEqual$3(current2.layers, detailLayers) ? current2 : { ...current2, layers: detailLayers };
282363
+ latestViewerStateRef.current = updated2;
282364
+ return updated2;
282365
+ }
282150
282366
  const { projectionScale, projectionOrientation, position: position2 } = current2;
282151
- const rotChangedNow = !nearEq(spatialRotationX, prevCoordsRef.current.rx, ROTATION_EPS) || !nearEq(spatialRotationY, prevCoordsRef.current.ry, ROTATION_EPS) || !nearEq(spatialRotationZ, prevCoordsRef.current.rz, ROTATION_EPS) || !nearEq(spatialRotationOrbit, prevCoordsRef.current.orbit, ROTATION_EPS);
282152
- const zoomChangedNow = !nearEq(spatialZoom, prevCoordsRef.current.zoom, ROTATION_EPS);
282153
- const transChangedNow = !nearEq(spatialTargetX, prevCoordsRef.current.tx, ROTATION_EPS) || !nearEq(spatialTargetY, prevCoordsRef.current.ty, ROTATION_EPS);
282367
+ const rotChangedNow = is3dMode && (!nearEq(spatialRotationX, prevCoordsRef.current.rx, ROTATION_EPS) || !nearEq(spatialRotationY, prevCoordsRef.current.ry, ROTATION_EPS) || !nearEq(spatialRotationZ, prevCoordsRef.current.rz, ROTATION_EPS) || !nearEq(spatialRotationOrbit, prevCoordsRef.current.orbit, ROTATION_EPS));
282368
+ const zoomChangedNow = is3dMode && !nearEq(spatialZoom, prevCoordsRef.current.zoom, ROTATION_EPS);
282369
+ const transChangedNow = is3dMode && (!nearEq(spatialTargetX, prevCoordsRef.current.tx, ROTATION_EPS) || !nearEq(spatialTargetY, prevCoordsRef.current.ty, ROTATION_EPS));
282154
282370
  let nextProjectionScale = projectionScale;
282155
282371
  let nextPosition = position2;
282156
282372
  if (typeof spatialZoom === "number" && initialRenderCalibratorRef.current && lastInteractionSource.current !== LAST_INTERACTION_SOURCE.neuroglancer && zoomChangedNow) {
@@ -282171,7 +282387,7 @@ function NeuroglancerSubscriber(props) {
282171
282387
  }
282172
282388
  const vitessceRotationRaw = eulerToQuaternion(deg2rad(spatialRotationX ?? 0), deg2rad(spatialRotationOrbit ?? 0), deg2rad(spatialRotationZ ?? 0));
282173
282389
  const vitessceRotation = multiplyQuat(Q_Y_UP, vitessceRotationRaw);
282174
- const shouldForceInitialVitPush = !initialRotationPushedRef.current && valueGreaterThanEpsilon(vitessceRotation, projectionOrientation, ROTATION_EPS);
282390
+ const shouldForceInitialVitPush = is3dMode && !initialRotationPushedRef.current && valueGreaterThanEpsilon(vitessceRotation, projectionOrientation, ROTATION_EPS);
282175
282391
  const changedNowOrIInitialVitPush = rotChangedNow || zoomChangedNow || transChangedNow || shouldForceInitialVitPush;
282176
282392
  const src = lastInteractionSource.current ?? (changedNowOrIInitialVitPush ? LAST_INTERACTION_SOURCE.vitessce : null);
282177
282393
  let nextOrientation = projectionOrientation;
@@ -282258,7 +282474,10 @@ function NeuroglancerSubscriber(props) {
282258
282474
  spatialTargetY,
282259
282475
  initialViewerState,
282260
282476
  latestViewerStateIteration,
282261
- hasMatchingAnnotationSource
282477
+ hasMatchingAnnotationSource,
282478
+ detailMode,
282479
+ detailSegmentIds,
282480
+ is3dMode
282262
282481
  ]);
282263
282482
  const onSegmentHighlight = useCallback((obsId) => {
282264
282483
  const next4 = obsId != null ? String(obsId) : null;
@@ -282285,9 +282504,9 @@ function NeuroglancerSubscriber(props) {
282285
282504
  pointLayerScopes: showPointsLegend ? pointLayerScopes : void 0,
282286
282505
  pointLayerCoordination,
282287
282506
  pointMultiIndicesData
282288
- }) }), isMeshLoading ? jsx$1(Chip, { label: "Loading meshes...", size: "small", color: "primary", className: classes2.meshLoadingIndicator }) : null, jsx$1(NeuroglancerComp, { classes: classes2, onSegmentClick, onSelectHoveredCoords: onSegmentHighlight, viewerState: derivedViewerState, cellColorMapping: cellColorMappingByLayer, setViewerState: handleStateUpdate, onLayerLoadingChange: handleLayerLoadingChange, onAnnotationSourceReady, onViewerReady: (getFn) => {
282507
+ }) }), isMeshLoading ? jsx$1(Chip, { label: "Loading meshes...", size: "small", color: "primary", className: classes2.meshLoadingIndicator }) : null, jsx$1(NeuroglancerComp, { classes: classes2, onSegmentClick, onSelectHoveredCoords: detailMode ? void 0 : onSegmentHighlight, viewerState: derivedViewerState, cellColorMapping: cellColorMappingByLayer, setViewerState: handleStateUpdate, onLayerLoadingChange: handleLayerLoadingChange, onAnnotationSourceReady, onViewerReady: (getFn) => {
282289
282508
  getViewProjectionMatRef.current = getFn;
282290
- }, getMeshIdToCellId: (meshId) => meshIdToCellIdRef.current[meshId], cellsUrl, meshOpacity })] }) : null });
282509
+ }, getMeshIdToCellId: (meshId) => meshIdToCellIdRef.current[meshId], cellsUrl, meshOpacity, allowEmptySegments: detailMode })] }) : null });
282291
282510
  }
282292
282511
  const FEATURE_AGGREGATION_STRATEGIES = ["first", "last", "sum", "mean"];
282293
282512
  function CellSetExpressionPlotOptions(props) {
@@ -340451,6 +340670,17 @@ class ImageWrapper {
340451
340670
  const { labels: labels2, shape: shape2 } = Array.isArray(loader2.data) ? loader2.data[0] : loader2.data;
340452
340671
  return shape2[labels2.indexOf("z")];
340453
340672
  }
340673
+ /**
340674
+ * Clamp a z target to a valid plane index.
340675
+ * spatialTargetZ can hold a 3D camera target in scene units, which may
340676
+ * exceed the number of planes; geotiff throws on out-of-range indices.
340677
+ */
340678
+ getClampedZIndex(targetZ) {
340679
+ const numZ = this.getNumZ();
340680
+ if (!Number.isFinite(numZ) || !Number.isFinite(targetZ))
340681
+ return 0;
340682
+ return Math.min(Math.max(Math.floor(targetZ), 0), numZ - 1);
340683
+ }
340454
340684
  getNumT() {
340455
340685
  const loader2 = this.vivLoader;
340456
340686
  const { labels: labels2, shape: shape2 } = Array.isArray(loader2.data) ? loader2.data[0] : loader2.data;
@@ -340551,6 +340781,27 @@ class ImageWrapper {
340551
340781
  }
340552
340782
  return "BlackIsZero";
340553
340783
  }
340784
+ /**
340785
+ * Meters per 3D scene unit, i.e. the unit of getModelMatrix().
340786
+ * OME-TIFF: physicalSizeToMatrix divides by 1 um, so the scene is in µm
340787
+ * (only when physical sizes exist; otherwise pixels, unit unknown → null).
340788
+ * OME-Zarr: the model matrix is in the units of the NGFF axes.
340789
+ */
340790
+ getSceneMetersPerUnit() {
340791
+ const { metadata: metadata2 } = this.vivLoader;
340792
+ if (!metadata2)
340793
+ return null;
340794
+ if ("Pixels" in metadata2) {
340795
+ return this.hasPhysicalSize() ? 1e-6 : null;
340796
+ }
340797
+ if ("multiscales" in metadata2) {
340798
+ const axes = metadata2.multiscales?.[0]?.axes ?? [];
340799
+ const xAxis = axes.find((a2) => (typeof a2 === "string" ? a2 : a2?.name) === "x");
340800
+ const unit2 = typeof xAxis === "object" ? xAxis?.unit : null;
340801
+ return unit2 ? UNIT_TO_METERS[unit2.normalize("NFKC")] ?? null : null;
340802
+ }
340803
+ return null;
340804
+ }
340554
340805
  }
340555
340806
  class OmeZarrLoader extends AbstractTwoStepLoader {
340556
340807
  constructor(dataSource, params2) {
@@ -360756,6 +361007,7 @@ const baseCoordinationTypes = [
360756
361007
  new PluginCoordinationType(CoordinationType$1.SPATIAL_LAYER_COLOR, null, z.array(z.number()).length(3).nullable()),
360757
361008
  new PluginCoordinationType(CoordinationType$1.PIXEL_HIGHLIGHT, null, z.array(z.number()).length(3).nullable()),
360758
361009
  new PluginCoordinationType(CoordinationType$1.TOOLTIP_CROSSHAIRS_VISIBLE, true, z.boolean()),
361010
+ new PluginCoordinationType(CoordinationType$1.TOOLTIP_OBS_SETS_MODE, "all", z.enum(["all", "selected"])),
360759
361011
  new PluginCoordinationType(CoordinationType$1.LEGEND_VISIBLE, true, z.boolean()),
360760
361012
  new PluginCoordinationType(CoordinationType$1.SPATIAL_CHANNEL_LABELS_VISIBLE, true, z.boolean()),
360761
361013
  new PluginCoordinationType(CoordinationType$1.SPATIAL_CHANNEL_LABELS_ORIENTATION, "vertical", z.enum(["vertical", "horizontal"])),
@@ -360908,9 +361160,11 @@ export {
360908
361160
  z as a7,
360909
361161
  hasAnnotationControllerView as a8,
360910
361162
  addAnnotationControllerView as a9,
360911
- isAnyAnnotationEditing as aa,
360912
- enableAnnotationEditing as ab,
360913
- disableAnnotationEditing as ac,
361163
+ removeAnnotationControllerView as aa,
361164
+ hasAnyAnnotationStory as ab,
361165
+ isAnyAnnotationEditing as ac,
361166
+ enableAnnotationEditing as ad,
361167
+ disableAnnotationEditing as ae,
360914
361168
  getImageSize as b,
360915
361169
  commonjsGlobal$1 as c,
360916
361170
  requireAssign as d,