@vitessce/launcher 3.8.13 → 3.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{OrbitControls-CrApOBFU.js → OrbitControls-DyQ044MA.js} +1 -1
- package/dist/{ReactNeuroglancer-AxraaKy7.js → ReactNeuroglancer-BfXvm92G.js} +1 -1
- package/dist/{deflate-BtXXUoxP.js → deflate-DWFSnmER.js} +1 -1
- package/dist/{higlass-DVAhGN58.js → higlass-Baa_gFVD.js} +1 -1
- package/dist/{index-KpGEFZxo.js → index-BCLXgocP.js} +1331 -215
- package/dist/{index-Boz72UfP.js → index-C1eGTlSq.js} +3 -3
- package/dist/{index-B6nrHBqV.js → index-DHvGxl1H.js} +2 -2
- package/dist/index.js +1 -1
- package/dist/{jpeg-DxJqLfJK.js → jpeg-nKpt4803.js} +1 -1
- package/dist/{lerc-DdcYw8PI.js → lerc-BnXkSVBK.js} +1 -1
- package/dist/{lzw-C6871vN6.js → lzw-DLRhyzmK.js} +1 -1
- package/dist/{packbits-BRu_E5Nj.js → packbits-Bu2OcxM_.js} +1 -1
- package/dist/{raw-B9vaOZf2.js → raw-C2Cyu7qH.js} +1 -1
- package/dist/{troika-three-text.esm-C7-853Ar.js → troika-three-text.esm-DI_XyWCQ.js} +1 -1
- package/dist/{webimage-C6HswF-A.js → webimage-BUMl9PKo.js} +1 -1
- package/package.json +9 -9
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import React__default, { useState, useEffect, useCallback, useContext, forwardRef as forwardRef$1, useRef, useMemo as useMemo$1, createContext, createElement, isValidElement, cloneElement, Children, version as version$6, useLayoutEffect as useLayoutEffect$1, useImperativeHandle, PureComponent, Component as Component$1, Suspense, useReducer } from "react";
|
|
3
|
-
import { useLoaders, useCoordinationScopes, useCoordination, useDescription, useImageData, useReady, TitleInfo, useVitessceContainer, useSetWarning, useObsSetsData, useUrls, usePlotOptionsStyles, OptionsContainer, CellColorEncodingOption, OptionSelect, useComponentHover, useComponentViewInfo, useSetComponentHover, useSetComponentViewInfo, useInitialCoordination, useDeckCanvasSize, useMultiObsLabels, useObsEmbeddingData, useFeatureSelection, useObsFeatureMatrixIndices, useFeatureLabelsData, useExpandedFeatureLabelsMap, useSampleSetsData, useSampleEdgesData, useGetObsInfo, useUint8FeatureSelection, useExpressionValueGetter, useAuxiliaryCoordination, useHasLoader, useObsLocationsData, useObsLabelsData, useObsSegmentationsData, useNeighborhoodsData, useMergeCoordination, useCoordinationScopesBy, useMultiCoordinationScopesSecondaryNonNull, useMultiCoordinationScopesNonNull, useComplexCoordination, useComplexCoordinationSecondary, useGridItemSize, useMultiObsPoints, usePointMultiObsLabels, useMultiObsSpots, useSpotMultiObsSets, useSpotMultiFeatureLabels, useSpotMultiFeatureSelection, useSpotMultiObsFeatureMatrixIndices, useSegmentationMultiObsLocations, useMultiObsSegmentations, useSegmentationMultiObsSets, useSegmentationMultiFeatureSelection, useSegmentationMultiObsFeatureMatrixIndices, useMultiImages, useObsFeatureMatrixData, useUint8ObsFeatureMatrix, useGetObsMembership, PopperMenu, useComponentLayout, useClosestVitessceContainerSize, useWindowDimensions, useRemoveImageChannelInMetaCoordinationScopes, useAddImageChannelInMetaCoordinationScopes, useViewConfigStoreApi, useViewConfig, useSetViewConfig, createLoaders, useWarning, useGenomicProfilesData, useMatchingLoader, useColumnNameMapping, useFeatureStatsData, useObsSetStatsData, useAsyncFunction, useFeatureSetStatsData, useComparisonMetadata, logConfig, VitSContainer, createOnDrop } from "@vitessce/vit-s";
|
|
3
|
+
import { useLoaders, useCoordinationScopes, useCoordination, useDescription, useImageData, useReady, TitleInfo, useVitessceContainer, useSetWarning, useObsSetsData, useUrls, usePlotOptionsStyles, OptionsContainer, CellColorEncodingOption, OptionSelect, useComponentHover, useComponentViewInfo, useSetComponentHover, useSetComponentViewInfo, useInitialCoordination, useDeckCanvasSize, useMultiObsLabels, useObsEmbeddingData, useFeatureSelection, useObsFeatureMatrixIndices, useFeatureLabelsData, useExpandedFeatureLabelsMap, useSampleSetsData, useSampleEdgesData, useGetObsInfo, useUint8FeatureSelection, useExpressionValueGetter, useAuxiliaryCoordination, useHasLoader, useObsLocationsData, useObsLabelsData, useObsSegmentationsData, useNeighborhoodsData, useMergeCoordination, useCoordinationScopesBy, useMultiCoordinationScopesSecondaryNonNull, useMultiCoordinationScopesNonNull, useComplexCoordination, useComplexCoordinationSecondary, useGridItemSize, useMultiObsPoints, usePointMultiObsLabels, usePointMultiObsFeatureMatrixIndices, useMultiObsSpots, useSpotMultiObsSets, useSpotMultiFeatureLabels, useSpotMultiFeatureSelection, useSpotMultiObsFeatureMatrixIndices, useSegmentationMultiObsLocations, useMultiObsSegmentations, useSegmentationMultiObsSets, useSegmentationMultiFeatureSelection, useSegmentationMultiObsFeatureMatrixIndices, useMultiImages, useObsFeatureMatrixData, useUint8ObsFeatureMatrix, useGetObsMembership, PopperMenu, useComponentLayout, useClosestVitessceContainerSize, useWindowDimensions, useRemoveImageChannelInMetaCoordinationScopes, useAddImageChannelInMetaCoordinationScopes, useViewConfigStoreApi, useViewConfig, useSetViewConfig, createLoaders, useWarning, useGenomicProfilesData, useMatchingLoader, useColumnNameMapping, useFeatureStatsData, useObsSetStatsData, useAsyncFunction, useFeatureSetStatsData, useComparisonMetadata, logConfig, VitSContainer, createOnDrop } from "@vitessce/vit-s";
|
|
4
4
|
import * as ReactDOM from "react-dom";
|
|
5
5
|
import ReactDOM__default, { createPortal } from "react-dom";
|
|
6
6
|
function _mergeNamespaces(n3, m2) {
|
|
@@ -11197,6 +11197,7 @@ const CoordinationType$1 = {
|
|
|
11197
11197
|
OBS_SET_HIGHLIGHT: "obsSetHighlight",
|
|
11198
11198
|
OBS_SET_EXPANSION: "obsSetExpansion",
|
|
11199
11199
|
OBS_SET_COLOR: "obsSetColor",
|
|
11200
|
+
FEATURE_COLOR: "featureColor",
|
|
11200
11201
|
FEATURE_HIGHLIGHT: "featureHighlight",
|
|
11201
11202
|
FEATURE_SELECTION: "featureSelection",
|
|
11202
11203
|
FEATURE_SET_SELECTION: "featureSetSelection",
|
|
@@ -11801,6 +11802,8 @@ const COMPONENT_COORDINATION_TYPES = {
|
|
|
11801
11802
|
CoordinationType$1.OBS_SET_FILTER,
|
|
11802
11803
|
CoordinationType$1.OBS_SET_HIGHLIGHT,
|
|
11803
11804
|
CoordinationType$1.OBS_SET_COLOR,
|
|
11805
|
+
CoordinationType$1.FEATURE_COLOR,
|
|
11806
|
+
CoordinationType$1.FEATURE_FILTER_MODE,
|
|
11804
11807
|
CoordinationType$1.FEATURE_HIGHLIGHT,
|
|
11805
11808
|
CoordinationType$1.FEATURE_SELECTION,
|
|
11806
11809
|
CoordinationType$1.FEATURE_VALUE_COLORMAP,
|
|
@@ -12015,6 +12018,8 @@ const COMPONENT_COORDINATION_TYPES = {
|
|
|
12015
12018
|
CoordinationType$1.SPATIAL_SPOT_STROKE_WIDTH,
|
|
12016
12019
|
CoordinationType$1.SPATIAL_LAYER_COLOR,
|
|
12017
12020
|
CoordinationType$1.OBS_COLOR_ENCODING,
|
|
12021
|
+
CoordinationType$1.FEATURE_COLOR,
|
|
12022
|
+
CoordinationType$1.FEATURE_FILTER_MODE,
|
|
12018
12023
|
CoordinationType$1.FEATURE_VALUE_COLORMAP,
|
|
12019
12024
|
CoordinationType$1.FEATURE_VALUE_COLORMAP_RANGE,
|
|
12020
12025
|
CoordinationType$1.FEATURE_SELECTION,
|
|
@@ -33315,7 +33320,7 @@ var _span$3;
|
|
|
33315
33320
|
const useUtilityClasses$1j = (ownerState) => {
|
|
33316
33321
|
const {
|
|
33317
33322
|
classes: classes2,
|
|
33318
|
-
contained,
|
|
33323
|
+
contained: contained2,
|
|
33319
33324
|
size: size2,
|
|
33320
33325
|
disabled,
|
|
33321
33326
|
error: error2,
|
|
@@ -33324,7 +33329,7 @@ const useUtilityClasses$1j = (ownerState) => {
|
|
|
33324
33329
|
required: required2
|
|
33325
33330
|
} = ownerState;
|
|
33326
33331
|
const slots = {
|
|
33327
|
-
root: ["root", disabled && "disabled", error2 && "error", size2 && `size${capitalize$1(size2)}`,
|
|
33332
|
+
root: ["root", disabled && "disabled", error2 && "error", size2 && `size${capitalize$1(size2)}`, contained2 && "contained", focused && "focused", filled && "filled", required2 && "required"]
|
|
33328
33333
|
};
|
|
33329
33334
|
return composeClasses(slots, getFormHelperTextUtilityClasses, classes2);
|
|
33330
33335
|
};
|
|
@@ -34817,6 +34822,90 @@ ListItemText.propTypes = {
|
|
|
34817
34822
|
*/
|
|
34818
34823
|
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])
|
|
34819
34824
|
};
|
|
34825
|
+
function getListItemIconUtilityClass(slot) {
|
|
34826
|
+
return generateUtilityClass("MuiListItemIcon", slot);
|
|
34827
|
+
}
|
|
34828
|
+
const listItemIconClasses = generateUtilityClasses("MuiListItemIcon", ["root", "alignItemsFlexStart"]);
|
|
34829
|
+
const useUtilityClasses$1d = (ownerState) => {
|
|
34830
|
+
const {
|
|
34831
|
+
alignItems,
|
|
34832
|
+
classes: classes2
|
|
34833
|
+
} = ownerState;
|
|
34834
|
+
const slots = {
|
|
34835
|
+
root: ["root", alignItems === "flex-start" && "alignItemsFlexStart"]
|
|
34836
|
+
};
|
|
34837
|
+
return composeClasses(slots, getListItemIconUtilityClass, classes2);
|
|
34838
|
+
};
|
|
34839
|
+
const ListItemIconRoot = styled("div", {
|
|
34840
|
+
name: "MuiListItemIcon",
|
|
34841
|
+
slot: "Root",
|
|
34842
|
+
overridesResolver: (props, styles2) => {
|
|
34843
|
+
const {
|
|
34844
|
+
ownerState
|
|
34845
|
+
} = props;
|
|
34846
|
+
return [styles2.root, ownerState.alignItems === "flex-start" && styles2.alignItemsFlexStart];
|
|
34847
|
+
}
|
|
34848
|
+
})(memoTheme(({
|
|
34849
|
+
theme
|
|
34850
|
+
}) => ({
|
|
34851
|
+
minWidth: 56,
|
|
34852
|
+
color: (theme.vars || theme).palette.action.active,
|
|
34853
|
+
flexShrink: 0,
|
|
34854
|
+
display: "inline-flex",
|
|
34855
|
+
variants: [{
|
|
34856
|
+
props: {
|
|
34857
|
+
alignItems: "flex-start"
|
|
34858
|
+
},
|
|
34859
|
+
style: {
|
|
34860
|
+
marginTop: 8
|
|
34861
|
+
}
|
|
34862
|
+
}]
|
|
34863
|
+
})));
|
|
34864
|
+
const ListItemIcon = /* @__PURE__ */ React.forwardRef(function ListItemIcon2(inProps, ref2) {
|
|
34865
|
+
const props = useDefaultProps({
|
|
34866
|
+
props: inProps,
|
|
34867
|
+
name: "MuiListItemIcon"
|
|
34868
|
+
});
|
|
34869
|
+
const {
|
|
34870
|
+
className,
|
|
34871
|
+
...other
|
|
34872
|
+
} = props;
|
|
34873
|
+
const context2 = React.useContext(ListContext);
|
|
34874
|
+
const ownerState = {
|
|
34875
|
+
...props,
|
|
34876
|
+
alignItems: context2.alignItems
|
|
34877
|
+
};
|
|
34878
|
+
const classes2 = useUtilityClasses$1d(ownerState);
|
|
34879
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(ListItemIconRoot, {
|
|
34880
|
+
className: clsx$1(classes2.root, className),
|
|
34881
|
+
ownerState,
|
|
34882
|
+
ref: ref2,
|
|
34883
|
+
...other
|
|
34884
|
+
});
|
|
34885
|
+
});
|
|
34886
|
+
ListItemIcon.propTypes = {
|
|
34887
|
+
// ┌────────────────────────────── Warning ──────────────────────────────┐
|
|
34888
|
+
// │ These PropTypes are generated from the TypeScript type definitions. │
|
|
34889
|
+
// │ To update them, edit the d.ts file and run `pnpm proptypes`. │
|
|
34890
|
+
// └─────────────────────────────────────────────────────────────────────┘
|
|
34891
|
+
/**
|
|
34892
|
+
* The content of the component, normally `Icon`, `SvgIcon`,
|
|
34893
|
+
* or a `@mui/icons-material` SVG icon element.
|
|
34894
|
+
*/
|
|
34895
|
+
children: PropTypes.node,
|
|
34896
|
+
/**
|
|
34897
|
+
* Override or extend the styles applied to the component.
|
|
34898
|
+
*/
|
|
34899
|
+
classes: PropTypes.object,
|
|
34900
|
+
/**
|
|
34901
|
+
* @ignore
|
|
34902
|
+
*/
|
|
34903
|
+
className: PropTypes.string,
|
|
34904
|
+
/**
|
|
34905
|
+
* The system prop that allows defining system overrides as well as additional CSS styles.
|
|
34906
|
+
*/
|
|
34907
|
+
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])
|
|
34908
|
+
};
|
|
34820
34909
|
function getScrollbarSize$1(win2 = window) {
|
|
34821
34910
|
const documentWidth = win2.document.documentElement.clientWidth;
|
|
34822
34911
|
return win2.innerWidth - documentWidth;
|
|
@@ -35068,7 +35157,7 @@ function getDividerUtilityClass(slot) {
|
|
|
35068
35157
|
return generateUtilityClass("MuiDivider", slot);
|
|
35069
35158
|
}
|
|
35070
35159
|
const dividerClasses = generateUtilityClasses("MuiDivider", ["root", "absolute", "fullWidth", "inset", "middle", "flexItem", "light", "vertical", "withChildren", "withChildrenVertical", "textAlignRight", "textAlignLeft", "wrapper", "wrapperVertical"]);
|
|
35071
|
-
const useUtilityClasses$
|
|
35160
|
+
const useUtilityClasses$1c = (ownerState) => {
|
|
35072
35161
|
const {
|
|
35073
35162
|
absolute: absolute2,
|
|
35074
35163
|
children: children3,
|
|
@@ -35282,7 +35371,7 @@ const Divider$1 = /* @__PURE__ */ React.forwardRef(function Divider2(inProps, re
|
|
|
35282
35371
|
textAlign: textAlign2,
|
|
35283
35372
|
variant
|
|
35284
35373
|
};
|
|
35285
|
-
const classes2 = useUtilityClasses$
|
|
35374
|
+
const classes2 = useUtilityClasses$1c(ownerState);
|
|
35286
35375
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(DividerRoot, {
|
|
35287
35376
|
as: component,
|
|
35288
35377
|
className: clsx$1(classes2.root, className),
|
|
@@ -35364,90 +35453,6 @@ Divider$1.propTypes = {
|
|
|
35364
35453
|
*/
|
|
35365
35454
|
variant: PropTypes.oneOfType([PropTypes.oneOf(["fullWidth", "inset", "middle"]), PropTypes.string])
|
|
35366
35455
|
};
|
|
35367
|
-
function getListItemIconUtilityClass(slot) {
|
|
35368
|
-
return generateUtilityClass("MuiListItemIcon", slot);
|
|
35369
|
-
}
|
|
35370
|
-
const listItemIconClasses = generateUtilityClasses("MuiListItemIcon", ["root", "alignItemsFlexStart"]);
|
|
35371
|
-
const useUtilityClasses$1c = (ownerState) => {
|
|
35372
|
-
const {
|
|
35373
|
-
alignItems,
|
|
35374
|
-
classes: classes2
|
|
35375
|
-
} = ownerState;
|
|
35376
|
-
const slots = {
|
|
35377
|
-
root: ["root", alignItems === "flex-start" && "alignItemsFlexStart"]
|
|
35378
|
-
};
|
|
35379
|
-
return composeClasses(slots, getListItemIconUtilityClass, classes2);
|
|
35380
|
-
};
|
|
35381
|
-
const ListItemIconRoot = styled("div", {
|
|
35382
|
-
name: "MuiListItemIcon",
|
|
35383
|
-
slot: "Root",
|
|
35384
|
-
overridesResolver: (props, styles2) => {
|
|
35385
|
-
const {
|
|
35386
|
-
ownerState
|
|
35387
|
-
} = props;
|
|
35388
|
-
return [styles2.root, ownerState.alignItems === "flex-start" && styles2.alignItemsFlexStart];
|
|
35389
|
-
}
|
|
35390
|
-
})(memoTheme(({
|
|
35391
|
-
theme
|
|
35392
|
-
}) => ({
|
|
35393
|
-
minWidth: 56,
|
|
35394
|
-
color: (theme.vars || theme).palette.action.active,
|
|
35395
|
-
flexShrink: 0,
|
|
35396
|
-
display: "inline-flex",
|
|
35397
|
-
variants: [{
|
|
35398
|
-
props: {
|
|
35399
|
-
alignItems: "flex-start"
|
|
35400
|
-
},
|
|
35401
|
-
style: {
|
|
35402
|
-
marginTop: 8
|
|
35403
|
-
}
|
|
35404
|
-
}]
|
|
35405
|
-
})));
|
|
35406
|
-
const ListItemIcon = /* @__PURE__ */ React.forwardRef(function ListItemIcon2(inProps, ref2) {
|
|
35407
|
-
const props = useDefaultProps({
|
|
35408
|
-
props: inProps,
|
|
35409
|
-
name: "MuiListItemIcon"
|
|
35410
|
-
});
|
|
35411
|
-
const {
|
|
35412
|
-
className,
|
|
35413
|
-
...other
|
|
35414
|
-
} = props;
|
|
35415
|
-
const context2 = React.useContext(ListContext);
|
|
35416
|
-
const ownerState = {
|
|
35417
|
-
...props,
|
|
35418
|
-
alignItems: context2.alignItems
|
|
35419
|
-
};
|
|
35420
|
-
const classes2 = useUtilityClasses$1c(ownerState);
|
|
35421
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(ListItemIconRoot, {
|
|
35422
|
-
className: clsx$1(classes2.root, className),
|
|
35423
|
-
ownerState,
|
|
35424
|
-
ref: ref2,
|
|
35425
|
-
...other
|
|
35426
|
-
});
|
|
35427
|
-
});
|
|
35428
|
-
ListItemIcon.propTypes = {
|
|
35429
|
-
// ┌────────────────────────────── Warning ──────────────────────────────┐
|
|
35430
|
-
// │ These PropTypes are generated from the TypeScript type definitions. │
|
|
35431
|
-
// │ To update them, edit the d.ts file and run `pnpm proptypes`. │
|
|
35432
|
-
// └─────────────────────────────────────────────────────────────────────┘
|
|
35433
|
-
/**
|
|
35434
|
-
* The content of the component, normally `Icon`, `SvgIcon`,
|
|
35435
|
-
* or a `@mui/icons-material` SVG icon element.
|
|
35436
|
-
*/
|
|
35437
|
-
children: PropTypes.node,
|
|
35438
|
-
/**
|
|
35439
|
-
* Override or extend the styles applied to the component.
|
|
35440
|
-
*/
|
|
35441
|
-
classes: PropTypes.object,
|
|
35442
|
-
/**
|
|
35443
|
-
* @ignore
|
|
35444
|
-
*/
|
|
35445
|
-
className: PropTypes.string,
|
|
35446
|
-
/**
|
|
35447
|
-
* The system prop that allows defining system overrides as well as additional CSS styles.
|
|
35448
|
-
*/
|
|
35449
|
-
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])
|
|
35450
|
-
};
|
|
35451
35456
|
function getMenuItemUtilityClass(slot) {
|
|
35452
35457
|
return generateUtilityClass("MuiMenuItem", slot);
|
|
35453
35458
|
}
|
|
@@ -171404,14 +171409,14 @@ class RBush {
|
|
|
171404
171409
|
search(bbox2) {
|
|
171405
171410
|
let node2 = this.data;
|
|
171406
171411
|
const result = [];
|
|
171407
|
-
if (!intersects$
|
|
171412
|
+
if (!intersects$4(bbox2, node2)) return result;
|
|
171408
171413
|
const toBBox = this.toBBox;
|
|
171409
171414
|
const nodesToSearch = [];
|
|
171410
171415
|
while (node2) {
|
|
171411
171416
|
for (let i2 = 0; i2 < node2.children.length; i2++) {
|
|
171412
171417
|
const child = node2.children[i2];
|
|
171413
171418
|
const childBBox = node2.leaf ? toBBox(child) : child;
|
|
171414
|
-
if (intersects$
|
|
171419
|
+
if (intersects$4(bbox2, childBBox)) {
|
|
171415
171420
|
if (node2.leaf) result.push(child);
|
|
171416
171421
|
else if (contains$3(bbox2, childBBox)) this._all(child, result);
|
|
171417
171422
|
else nodesToSearch.push(child);
|
|
@@ -171423,13 +171428,13 @@ class RBush {
|
|
|
171423
171428
|
}
|
|
171424
171429
|
collides(bbox2) {
|
|
171425
171430
|
let node2 = this.data;
|
|
171426
|
-
if (!intersects$
|
|
171431
|
+
if (!intersects$4(bbox2, node2)) return false;
|
|
171427
171432
|
const nodesToSearch = [];
|
|
171428
171433
|
while (node2) {
|
|
171429
171434
|
for (let i2 = 0; i2 < node2.children.length; i2++) {
|
|
171430
171435
|
const child = node2.children[i2];
|
|
171431
171436
|
const childBBox = node2.leaf ? this.toBBox(child) : child;
|
|
171432
|
-
if (intersects$
|
|
171437
|
+
if (intersects$4(bbox2, childBBox)) {
|
|
171433
171438
|
if (node2.leaf || contains$3(bbox2, childBBox)) return true;
|
|
171434
171439
|
nodesToSearch.push(child);
|
|
171435
171440
|
}
|
|
@@ -171741,7 +171746,7 @@ function intersectionArea(a2, b2) {
|
|
|
171741
171746
|
function contains$3(a2, b2) {
|
|
171742
171747
|
return a2.minX <= b2.minX && a2.minY <= b2.minY && b2.maxX <= a2.maxX && b2.maxY <= a2.maxY;
|
|
171743
171748
|
}
|
|
171744
|
-
function intersects$
|
|
171749
|
+
function intersects$4(a2, b2) {
|
|
171745
171750
|
return b2.minX <= a2.maxX && b2.minY <= a2.maxY && b2.maxX >= a2.minX && b2.maxY >= a2.minY;
|
|
171746
171751
|
}
|
|
171747
171752
|
function createNode(children3) {
|
|
@@ -210603,22 +210608,22 @@ async function getDecoder(fileDirectory) {
|
|
|
210603
210608
|
const Decoder = await importFn();
|
|
210604
210609
|
return new Decoder(fileDirectory);
|
|
210605
210610
|
}
|
|
210606
|
-
addDecoder([void 0, 1], () => import("./raw-
|
|
210607
|
-
addDecoder(5, () => import("./lzw-
|
|
210611
|
+
addDecoder([void 0, 1], () => import("./raw-C2Cyu7qH.js").then((m2) => m2.default));
|
|
210612
|
+
addDecoder(5, () => import("./lzw-DLRhyzmK.js").then((m2) => m2.default));
|
|
210608
210613
|
addDecoder(6, () => {
|
|
210609
210614
|
throw new Error("old style JPEG compression is not supported.");
|
|
210610
210615
|
});
|
|
210611
|
-
addDecoder(7, () => import("./jpeg-
|
|
210612
|
-
addDecoder([8, 32946], () => import("./deflate-
|
|
210613
|
-
addDecoder(32773, () => import("./packbits-
|
|
210616
|
+
addDecoder(7, () => import("./jpeg-nKpt4803.js").then((m2) => m2.default));
|
|
210617
|
+
addDecoder([8, 32946], () => import("./deflate-DWFSnmER.js").then((m2) => m2.default));
|
|
210618
|
+
addDecoder(32773, () => import("./packbits-Bu2OcxM_.js").then((m2) => m2.default));
|
|
210614
210619
|
addDecoder(
|
|
210615
210620
|
34887,
|
|
210616
|
-
() => import("./lerc-
|
|
210621
|
+
() => import("./lerc-BnXkSVBK.js").then(async (m2) => {
|
|
210617
210622
|
await m2.zstd.init();
|
|
210618
210623
|
return m2;
|
|
210619
210624
|
}).then((m2) => m2.default)
|
|
210620
210625
|
);
|
|
210621
|
-
addDecoder(50001, () => import("./webimage-
|
|
210626
|
+
addDecoder(50001, () => import("./webimage-BUMl9PKo.js").then((m2) => m2.default));
|
|
210622
210627
|
function copyNewSize(array2, width2, height2, samplesPerPixel = 1) {
|
|
210623
210628
|
return new (Object.getPrototypeOf(array2)).constructor(width2 * height2 * samplesPerPixel);
|
|
210624
210629
|
}
|
|
@@ -232777,6 +232782,7 @@ function Legend(props) {
|
|
|
232777
232782
|
positionRelative = false,
|
|
232778
232783
|
highContrast = false,
|
|
232779
232784
|
obsType,
|
|
232785
|
+
isPointsLayer = false,
|
|
232780
232786
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
232781
232787
|
featureType: _featureType = void 0,
|
|
232782
232788
|
// Unused but accepted for API compatibility
|
|
@@ -232784,6 +232790,9 @@ function Legend(props) {
|
|
|
232784
232790
|
considerSelections = true,
|
|
232785
232791
|
obsColorEncoding,
|
|
232786
232792
|
featureSelection,
|
|
232793
|
+
featureFilterMode,
|
|
232794
|
+
featureColor,
|
|
232795
|
+
featureIndex,
|
|
232787
232796
|
featureLabelsMap,
|
|
232788
232797
|
featureValueColormap,
|
|
232789
232798
|
featureValueColormapRange,
|
|
@@ -232827,15 +232836,94 @@ function Legend(props) {
|
|
|
232827
232836
|
debouncedSetRange(rangeValue);
|
|
232828
232837
|
}
|
|
232829
232838
|
}, [debouncedSetRange]);
|
|
232839
|
+
const obsLabel = capitalize$3(obsType ?? null);
|
|
232830
232840
|
const isDarkTheme = theme === "dark";
|
|
232831
|
-
const isStaticColor = obsColorEncoding === "spatialChannelColor" || obsColorEncoding === "spatialLayerColor";
|
|
232832
|
-
const isSetColor = obsColorEncoding === "cellSetSelection";
|
|
232841
|
+
const isStaticColor = !isPointsLayer && (obsColorEncoding === "spatialChannelColor" || obsColorEncoding === "spatialLayerColor");
|
|
232842
|
+
const isSetColor = !isPointsLayer && obsColorEncoding === "cellSetSelection";
|
|
232833
232843
|
const layerColor = Array.isArray(spatialLayerColor) && spatialLayerColor.length === 3 ? spatialLayerColor : getDefaultColor(theme ?? "light");
|
|
232834
232844
|
const channelColor = Array.isArray(spatialChannelColor) && spatialChannelColor.length === 3 ? spatialChannelColor : getDefaultColor(theme ?? "light");
|
|
232835
232845
|
const staticColor = obsColorEncoding === "spatialChannelColor" ? channelColor : layerColor;
|
|
232836
|
-
const visible = visibleProp && (!considerSelections || ["geneSelection", "geneExpression"].includes(obsColorEncoding ?? "") && featureSelection && Array.isArray(featureSelection) && featureSelection.length >= 1 || isSetColor && (obsSetSelection?.length ?? 0) > 0 && (obsSetColor?.length ?? 0) > 0 || isStaticColor);
|
|
232846
|
+
const visible = visibleProp && (!considerSelections || ["geneSelection", "geneExpression"].includes(obsColorEncoding ?? "") && featureSelection && Array.isArray(featureSelection) && featureSelection.length >= 1 || isSetColor && (obsSetSelection?.length ?? 0) > 0 && (obsSetColor?.length ?? 0) > 0 || isStaticColor || isPointsLayer);
|
|
232847
|
+
const pointsLegendElements = [];
|
|
232848
|
+
if (isPointsLayer) {
|
|
232849
|
+
const MAX_NUM_COLORS = 10;
|
|
232850
|
+
const hasFeatureSelection = Array.isArray(featureSelection) && featureSelection.length > 0;
|
|
232851
|
+
const showUnselected = featureFilterMode !== "featureSelection";
|
|
232852
|
+
if (obsColorEncoding === "spatialLayerColor") {
|
|
232853
|
+
if (!hasFeatureSelection) {
|
|
232854
|
+
pointsLegendElements.push({
|
|
232855
|
+
name: obsLabel,
|
|
232856
|
+
color: staticColor
|
|
232857
|
+
});
|
|
232858
|
+
} else {
|
|
232859
|
+
const limitedFeatureSelection = featureSelection.slice(0, MAX_NUM_COLORS);
|
|
232860
|
+
limitedFeatureSelection.forEach((featureName) => {
|
|
232861
|
+
pointsLegendElements.push({
|
|
232862
|
+
name: featureName,
|
|
232863
|
+
color: staticColor
|
|
232864
|
+
});
|
|
232865
|
+
});
|
|
232866
|
+
}
|
|
232867
|
+
} else if (obsColorEncoding === "geneSelection") {
|
|
232868
|
+
if (!hasFeatureSelection) {
|
|
232869
|
+
pointsLegendElements.push({
|
|
232870
|
+
name: obsLabel,
|
|
232871
|
+
color: staticColor
|
|
232872
|
+
});
|
|
232873
|
+
} else {
|
|
232874
|
+
const limitedFeatureSelection = featureSelection.slice(0, MAX_NUM_COLORS);
|
|
232875
|
+
limitedFeatureSelection.forEach((featureName) => {
|
|
232876
|
+
const featureColorMatch = Array.isArray(featureColor) ? featureColor.find((fc) => fc.name === featureName)?.color : null;
|
|
232877
|
+
pointsLegendElements.push({
|
|
232878
|
+
name: featureName,
|
|
232879
|
+
// If no color is specified for this feature, use staticColor.
|
|
232880
|
+
color: featureColorMatch ?? staticColor
|
|
232881
|
+
});
|
|
232882
|
+
});
|
|
232883
|
+
}
|
|
232884
|
+
} else if (obsColorEncoding === "randomByFeature") {
|
|
232885
|
+
if (!hasFeatureSelection) {
|
|
232886
|
+
pointsLegendElements.push({
|
|
232887
|
+
name: obsLabel,
|
|
232888
|
+
// For now, using black and white for this.
|
|
232889
|
+
// (It should not match any color in PALETTE)
|
|
232890
|
+
color: isDarkTheme ? [255, 255, 255] : [0, 0, 0]
|
|
232891
|
+
});
|
|
232892
|
+
} else {
|
|
232893
|
+
const limitedFeatureSelection = featureSelection.slice(0, MAX_NUM_COLORS);
|
|
232894
|
+
limitedFeatureSelection.forEach((featureName) => {
|
|
232895
|
+
const varIndex = (featureIndex ?? []).indexOf(featureName);
|
|
232896
|
+
const featureColorMatch = varIndex >= 0 ? PALETTE[varIndex % PALETTE.length] : null;
|
|
232897
|
+
pointsLegendElements.push({
|
|
232898
|
+
name: featureName,
|
|
232899
|
+
// If no color is specified for this feature, use staticColor.
|
|
232900
|
+
color: featureColorMatch ?? staticColor
|
|
232901
|
+
});
|
|
232902
|
+
});
|
|
232903
|
+
}
|
|
232904
|
+
} else if (obsColorEncoding === "random") {
|
|
232905
|
+
pointsLegendElements.push({
|
|
232906
|
+
name: obsLabel,
|
|
232907
|
+
// For now, using black and white for this.
|
|
232908
|
+
// (It should not match any color in PALETTE)
|
|
232909
|
+
color: isDarkTheme ? [255, 255, 255] : [0, 0, 0]
|
|
232910
|
+
});
|
|
232911
|
+
}
|
|
232912
|
+
if (showUnselected) {
|
|
232913
|
+
pointsLegendElements.push({
|
|
232914
|
+
name: "Unselected",
|
|
232915
|
+
color: getDefaultColor(theme ?? "light")
|
|
232916
|
+
});
|
|
232917
|
+
}
|
|
232918
|
+
}
|
|
232837
232919
|
const levelZeroNames = useMemo$1(() => Array.from(new Set(obsSetSelection?.map((setPath) => setPath[0]) || [])), [obsSetSelection]);
|
|
232838
|
-
const dynamicHeight =
|
|
232920
|
+
const dynamicHeight = isPointsLayer ? (
|
|
232921
|
+
// Height logic for points layers.
|
|
232922
|
+
pointsLegendElements.length * (rectHeight + rectMarginY) + titleHeight
|
|
232923
|
+
) : (
|
|
232924
|
+
// Height logic for non-points layers.
|
|
232925
|
+
isSetColor && obsSetSelection ? levelZeroNames.length * titleHeight + (obsSetSelection?.length ?? 0) * (rectHeight + rectMarginY) : height2 + (!pointsVisible && contoursVisible ? 25 : 0)
|
|
232926
|
+
);
|
|
232839
232927
|
const availHeight = maxHeight2 !== null ? Math.max(0, maxHeight2 - 4) : Infinity;
|
|
232840
232928
|
const needsScroll = Number.isFinite(availHeight) && dynamicHeight > availHeight + 1;
|
|
232841
232929
|
useEffect(() => {
|
|
@@ -232847,8 +232935,8 @@ function Legend(props) {
|
|
|
232847
232935
|
svg2.selectAll("g").remove();
|
|
232848
232936
|
svg2.attr("width", width2).attr("height", dynamicHeight);
|
|
232849
232937
|
const g2 = svg2.append("g").attr("width", width2).attr("height", dynamicHeight);
|
|
232850
|
-
const showInteractiveSlider2 = setFeatureValueColormapRange && ["geneSelection", "geneExpression"].includes(obsColorEncoding ?? "") && pointsVisible && featureValueColormap;
|
|
232851
|
-
if (!considerSelections || ["geneSelection", "geneExpression"].includes(obsColorEncoding ?? "")) {
|
|
232938
|
+
const showInteractiveSlider2 = !isPointsLayer && setFeatureValueColormapRange && ["geneSelection", "geneExpression"].includes(obsColorEncoding ?? "") && pointsVisible && featureValueColormap;
|
|
232939
|
+
if (!isPointsLayer && (!considerSelections || ["geneSelection", "geneExpression"].includes(obsColorEncoding ?? ""))) {
|
|
232852
232940
|
const combinedExtent = combineExtents(extent2 ?? null, featureAggregationStrategy ?? null) || [0, 1];
|
|
232853
232941
|
const [xMin, xMax] = combinedExtent;
|
|
232854
232942
|
if (featureValueColormap && pointsVisible) {
|
|
@@ -232908,10 +232996,10 @@ function Legend(props) {
|
|
|
232908
232996
|
});
|
|
232909
232997
|
}
|
|
232910
232998
|
}
|
|
232911
|
-
if (isStaticColor) {
|
|
232999
|
+
if (!isPointsLayer && isStaticColor) {
|
|
232912
233000
|
g2.append("rect").attr("x", 0).attr("y", titleHeight).attr("width", width2 - 4).attr("height", rectHeight).attr("fill", `rgb(${staticColor[0]},${staticColor[1]},${staticColor[2]})`);
|
|
232913
233001
|
}
|
|
232914
|
-
if (isSetColor && obsSetSelection && obsSetColor) {
|
|
233002
|
+
if (!isPointsLayer && isSetColor && obsSetSelection && obsSetColor) {
|
|
232915
233003
|
const obsSetSelectionByLevelZero = {};
|
|
232916
233004
|
obsSetSelection.forEach((setPath) => {
|
|
232917
233005
|
const levelZeroName = setPath[0];
|
|
@@ -232932,6 +233020,16 @@ function Legend(props) {
|
|
|
232932
233020
|
});
|
|
232933
233021
|
});
|
|
232934
233022
|
}
|
|
233023
|
+
if (isPointsLayer) {
|
|
233024
|
+
let y2 = 0;
|
|
233025
|
+
g2.append("text").attr("text-anchor", "start").attr("dominant-baseline", "hanging").attr("x", 0).attr("y", y2).text("Points").style("font-size", "9px").style("fill", foregroundColor);
|
|
233026
|
+
y2 += titleHeight;
|
|
233027
|
+
pointsLegendElements.forEach(({ name: name2, color: color2 }) => {
|
|
233028
|
+
g2.append("rect").attr("x", 0).attr("y", y2).attr("width", rectHeight).attr("height", rectHeight).attr("fill", `rgb(${color2[0]},${color2[1]},${color2[2]})`);
|
|
233029
|
+
g2.append("text").attr("text-anchor", "start").attr("dominant-baseline", "hanging").attr("x", rectHeight + rectMarginX).attr("y", y2).text(name2).style("font-size", "9px").style("fill", foregroundColor);
|
|
233030
|
+
y2 += rectHeight + rectMarginY;
|
|
233031
|
+
});
|
|
233032
|
+
}
|
|
232935
233033
|
const featureSelectionLabelRaw = featureSelection && featureSelection.length >= 1 && !isStaticColor ? featureSelection.map((geneName) => featureLabelsMap?.get(geneName) || featureLabelsMap?.get(cleanFeatureId(geneName)) || geneName) : null;
|
|
232936
233034
|
let featureSelectionLabelRawStr = "";
|
|
232937
233035
|
if (featureAggregationStrategy === "first") {
|
|
@@ -232958,12 +233056,11 @@ function Legend(props) {
|
|
|
232958
233056
|
}
|
|
232959
233057
|
const combinedMissing = combineMissings(missing ?? null, featureAggregationStrategy ?? null);
|
|
232960
233058
|
const featureSelectionLabel = combinedMissing ? `${featureSelectionLabelRawStr} (${Math.round(combinedMissing * 100)}% NaN)` : featureSelectionLabelRawStr;
|
|
232961
|
-
const obsLabel = capitalize$3(obsType ?? null);
|
|
232962
233059
|
const featureLabel = considerSelections ? featureSelectionLabel || capitalize$3(featureValueType ?? null) : capitalize$3(featureValueType ?? null);
|
|
232963
233060
|
const mainLabel = showObsLabel ? obsLabel : featureLabel;
|
|
232964
233061
|
const subLabel = showObsLabel ? featureLabel : null;
|
|
232965
233062
|
const hasSubLabel = subLabel !== null;
|
|
232966
|
-
if (!isSetColor) {
|
|
233063
|
+
if (!isPointsLayer && !isSetColor) {
|
|
232967
233064
|
g2.append("text").attr("text-anchor", hasSubLabel ? "start" : "end").attr("dominant-baseline", "hanging").attr("x", hasSubLabel ? 0 : width2 - 4).attr("y", 0).text(mainLabel ?? "").style("font-size", "10px").style("fill", foregroundColor);
|
|
232968
233065
|
if (hasSubLabel) {
|
|
232969
233066
|
g2.append("text").attr("text-anchor", "end").attr("dominant-baseline", "hanging").attr("x", width2 - 5).attr("y", titleHeight + rectHeight).text(subLabel ?? "").style("font-size", "9px").style("fill", foregroundColor);
|
|
@@ -233002,7 +233099,7 @@ function Legend(props) {
|
|
|
233002
233099
|
showObsLabel,
|
|
233003
233100
|
staticColor
|
|
233004
233101
|
]);
|
|
233005
|
-
const showInteractiveSlider = setFeatureValueColormapRange && ["geneSelection", "geneExpression"].includes(obsColorEncoding ?? "") && pointsVisible && featureValueColormap;
|
|
233102
|
+
const showInteractiveSlider = !isPointsLayer && setFeatureValueColormapRange && ["geneSelection", "geneExpression"].includes(obsColorEncoding ?? "") && pointsVisible && featureValueColormap;
|
|
233006
233103
|
const globalExtent = useMemo$1(() => {
|
|
233007
233104
|
const combined = combineExtents(extent2 ?? null, featureAggregationStrategy ?? null);
|
|
233008
233105
|
return combined || [0, 1];
|
|
@@ -233075,7 +233172,8 @@ function MultiLegend(props) {
|
|
|
233075
233172
|
spotMultiFeatureLabels,
|
|
233076
233173
|
// Points
|
|
233077
233174
|
pointLayerScopes,
|
|
233078
|
-
pointLayerCoordination
|
|
233175
|
+
pointLayerCoordination,
|
|
233176
|
+
pointMultiIndicesData
|
|
233079
233177
|
} = props;
|
|
233080
233178
|
const { classes: classes2 } = useStyles$p();
|
|
233081
233179
|
const reversedSegmentationLayerScopes = useMemo$1(() => [...segmentationLayerScopes || []].reverse(), [segmentationLayerScopes]);
|
|
@@ -233086,7 +233184,8 @@ function MultiLegend(props) {
|
|
|
233086
233184
|
const layerSetters = pointLayerCoordination?.[1]?.[layerScope];
|
|
233087
233185
|
if (!layerCoordination)
|
|
233088
233186
|
return null;
|
|
233089
|
-
const { spatialLayerVisible, obsColorEncoding, obsType, featureType, featureValueType, featureSelection, featureValueColormap, featureValueColormapRange, spatialLayerColor, legendVisible } = layerCoordination;
|
|
233187
|
+
const { spatialLayerVisible, obsColorEncoding, obsType, featureType, featureValueType, featureSelection, featureColor, featureFilterMode, featureValueColormap, featureValueColormapRange, spatialLayerColor, legendVisible } = layerCoordination;
|
|
233188
|
+
const pointIndicesData = pointMultiIndicesData?.[layerScope];
|
|
233090
233189
|
const { setFeatureValueColormapRange } = layerSetters || {};
|
|
233091
233190
|
const isStaticColor = obsColorEncoding === "spatialLayerColor";
|
|
233092
233191
|
const height2 = isStaticColor ? 20 : 36;
|
|
@@ -233103,6 +233202,10 @@ function MultiLegend(props) {
|
|
|
233103
233202
|
obsColorEncoding,
|
|
233104
233203
|
spatialLayerColor,
|
|
233105
233204
|
featureSelection,
|
|
233205
|
+
featureFilterMode,
|
|
233206
|
+
featureColor,
|
|
233207
|
+
featureIndex: pointIndicesData?.featureIndex,
|
|
233208
|
+
isPointsLayer: true,
|
|
233106
233209
|
// featureLabelsMap={featureLabelsMap} // TODO
|
|
233107
233210
|
featureValueColormap: featureValueColormap || "viridis",
|
|
233108
233211
|
featureValueColormapRange: featureValueColormapRange || [0, 1],
|
|
@@ -253577,6 +253680,7 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
|
|
|
253577
253680
|
this.obsSpotsQuadTree = {};
|
|
253578
253681
|
this.obsPointsData = {};
|
|
253579
253682
|
this.obsPointsQuadTree = {};
|
|
253683
|
+
this.obsPointsLoadingStatus = {};
|
|
253580
253684
|
this.imageLayers = [];
|
|
253581
253685
|
this.obsSegmentationsLayers = [];
|
|
253582
253686
|
this.obsSpotsLayers = [];
|
|
@@ -253757,10 +253861,131 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
|
|
|
253757
253861
|
});
|
|
253758
253862
|
}
|
|
253759
253863
|
createPointLayer(layerScope, layerCoordination, layerObsPoints) {
|
|
253760
|
-
const { theme, delegateHover, targetZ } = this.props;
|
|
253761
|
-
const { spatialLayerVisible, spatialLayerOpacity, obsColorEncoding, spatialLayerColor } = layerCoordination;
|
|
253762
|
-
const
|
|
253864
|
+
const { theme, delegateHover, targetZ, pointMatrixIndices, setTiledPointsLoadingProgress } = this.props;
|
|
253865
|
+
const { spatialLayerVisible, spatialLayerOpacity, obsColorEncoding, spatialLayerColor, featureSelection, featureFilterMode, featureColor } = layerCoordination;
|
|
253866
|
+
const pointFeatureIndex = pointMatrixIndices?.[layerScope]?.featureIndex;
|
|
253867
|
+
let featureIndices = [];
|
|
253868
|
+
if (Array.isArray(featureSelection) && featureSelection.length >= 1) {
|
|
253869
|
+
if (pointFeatureIndex) {
|
|
253870
|
+
featureIndices = featureSelection.map((geneName) => pointFeatureIndex.indexOf(geneName)).filter((i2) => i2 >= 0);
|
|
253871
|
+
}
|
|
253872
|
+
}
|
|
253763
253873
|
const staticColor = Array.isArray(spatialLayerColor) && spatialLayerColor.length === 3 ? spatialLayerColor : getDefaultColor(theme);
|
|
253874
|
+
const defaultColor = getDefaultColor(theme);
|
|
253875
|
+
let getFillColor = null;
|
|
253876
|
+
const hasFeatureSelection = Array.isArray(featureSelection) && featureSelection.length > 0;
|
|
253877
|
+
const showUnselected = featureFilterMode !== "featureSelection";
|
|
253878
|
+
const hasMultipleFeaturesSelected = Array.isArray(featureIndices) && featureIndices.length > 1;
|
|
253879
|
+
if (obsColorEncoding === "spatialLayerColor") {
|
|
253880
|
+
getFillColor = (object2, { index: index2, data: data2, target: target2 }) => {
|
|
253881
|
+
if (!hasFeatureSelection || featureIndices.includes(data2.src.featureIndices[index2])) {
|
|
253882
|
+
target2[0] = staticColor[0];
|
|
253883
|
+
target2[1] = staticColor[1];
|
|
253884
|
+
target2[2] = staticColor[2];
|
|
253885
|
+
target2[3] = 255;
|
|
253886
|
+
return target2;
|
|
253887
|
+
}
|
|
253888
|
+
if (!showUnselected) {
|
|
253889
|
+
if (hasMultipleFeaturesSelected) {
|
|
253890
|
+
target2[3] = 0;
|
|
253891
|
+
}
|
|
253892
|
+
return target2;
|
|
253893
|
+
}
|
|
253894
|
+
target2[0] = defaultColor[0];
|
|
253895
|
+
target2[1] = defaultColor[1];
|
|
253896
|
+
target2[2] = defaultColor[2];
|
|
253897
|
+
target2[3] = 255;
|
|
253898
|
+
return target2;
|
|
253899
|
+
};
|
|
253900
|
+
} else if (obsColorEncoding === "geneSelection") {
|
|
253901
|
+
getFillColor = (object2, { index: index2, data: data2, target: target2 }) => {
|
|
253902
|
+
if (!hasFeatureSelection) {
|
|
253903
|
+
target2[0] = staticColor[0];
|
|
253904
|
+
target2[1] = staticColor[1];
|
|
253905
|
+
target2[2] = staticColor[2];
|
|
253906
|
+
target2[3] = 255;
|
|
253907
|
+
return target2;
|
|
253908
|
+
}
|
|
253909
|
+
const isSelected = featureIndices.includes(data2.src.featureIndices[index2]);
|
|
253910
|
+
if (isSelected) {
|
|
253911
|
+
const featureName = pointFeatureIndex?.[data2.src.featureIndices[index2]];
|
|
253912
|
+
const featureColorMatch = Array.isArray(featureColor) ? featureColor.find((fc) => fc.name === featureName)?.color : null;
|
|
253913
|
+
if (featureColorMatch) {
|
|
253914
|
+
target2[0] = featureColorMatch[0];
|
|
253915
|
+
target2[1] = featureColorMatch[1];
|
|
253916
|
+
target2[2] = featureColorMatch[2];
|
|
253917
|
+
target2[3] = 255;
|
|
253918
|
+
return target2;
|
|
253919
|
+
}
|
|
253920
|
+
target2[0] = staticColor[0];
|
|
253921
|
+
target2[1] = staticColor[1];
|
|
253922
|
+
target2[2] = staticColor[2];
|
|
253923
|
+
target2[3] = 255;
|
|
253924
|
+
return target2;
|
|
253925
|
+
}
|
|
253926
|
+
if (!showUnselected) {
|
|
253927
|
+
if (hasMultipleFeaturesSelected) {
|
|
253928
|
+
target2[3] = 0;
|
|
253929
|
+
}
|
|
253930
|
+
return target2;
|
|
253931
|
+
}
|
|
253932
|
+
target2[0] = defaultColor[0];
|
|
253933
|
+
target2[1] = defaultColor[1];
|
|
253934
|
+
target2[2] = defaultColor[2];
|
|
253935
|
+
target2[3] = 255;
|
|
253936
|
+
return target2;
|
|
253937
|
+
};
|
|
253938
|
+
} else if (obsColorEncoding === "randomByFeature") {
|
|
253939
|
+
{
|
|
253940
|
+
getFillColor = (object2, { index: index2, data: data2, target: target2 }) => {
|
|
253941
|
+
if (!hasFeatureSelection || featureIndices.includes(data2.src.featureIndices[index2])) {
|
|
253942
|
+
const varIndex = data2.src.featureIndices[index2];
|
|
253943
|
+
const color2 = PALETTE[varIndex % PALETTE.length];
|
|
253944
|
+
target2[0] = color2[0];
|
|
253945
|
+
target2[1] = color2[1];
|
|
253946
|
+
target2[2] = color2[2];
|
|
253947
|
+
target2[3] = 255;
|
|
253948
|
+
return target2;
|
|
253949
|
+
}
|
|
253950
|
+
if (!showUnselected) {
|
|
253951
|
+
if (hasMultipleFeaturesSelected) {
|
|
253952
|
+
target2[3] = 0;
|
|
253953
|
+
}
|
|
253954
|
+
return target2;
|
|
253955
|
+
}
|
|
253956
|
+
target2[0] = defaultColor[0];
|
|
253957
|
+
target2[1] = defaultColor[1];
|
|
253958
|
+
target2[2] = defaultColor[2];
|
|
253959
|
+
target2[3] = 255;
|
|
253960
|
+
return target2;
|
|
253961
|
+
};
|
|
253962
|
+
}
|
|
253963
|
+
} else if (obsColorEncoding === "random") {
|
|
253964
|
+
{
|
|
253965
|
+
getFillColor = (object2, { index: index2, data: data2, target: target2 }) => {
|
|
253966
|
+
if (!hasFeatureSelection || featureIndices.includes(data2.src.featureIndices[index2])) {
|
|
253967
|
+
const color2 = PALETTE[index2 % PALETTE.length];
|
|
253968
|
+
target2[0] = color2[0];
|
|
253969
|
+
target2[1] = color2[1];
|
|
253970
|
+
target2[2] = color2[2];
|
|
253971
|
+
target2[3] = 255;
|
|
253972
|
+
return target2;
|
|
253973
|
+
}
|
|
253974
|
+
if (!showUnselected) {
|
|
253975
|
+
if (hasMultipleFeaturesSelected) {
|
|
253976
|
+
target2[3] = 0;
|
|
253977
|
+
}
|
|
253978
|
+
return target2;
|
|
253979
|
+
}
|
|
253980
|
+
target2[0] = defaultColor[0];
|
|
253981
|
+
target2[1] = defaultColor[1];
|
|
253982
|
+
target2[2] = defaultColor[2];
|
|
253983
|
+
target2[3] = 255;
|
|
253984
|
+
return target2;
|
|
253985
|
+
};
|
|
253986
|
+
}
|
|
253987
|
+
}
|
|
253988
|
+
const isStaticColor = obsColorEncoding === "spatialLayerColor";
|
|
253764
253989
|
const getMoleculeColor = (object2, { data: data2, index: index2, target: target2 }) => {
|
|
253765
253990
|
const obsId = data2.src.obsIndex[index2];
|
|
253766
253991
|
if (data2.src.obsLabelsMap && data2.src.uniqueObsLabels && data2.src.PALETTE) {
|
|
@@ -253772,11 +253997,131 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
|
|
|
253772
253997
|
}
|
|
253773
253998
|
return target2;
|
|
253774
253999
|
};
|
|
253775
|
-
const { obsPointsModelMatrix, obsPoints } = this.obsPointsData?.[layerScope]?.src ?? {};
|
|
253776
|
-
|
|
254000
|
+
const { obsPointsModelMatrix, obsPoints, obsPointsTilingType, loadPointsInRect } = this.obsPointsData?.[layerScope]?.src ?? {};
|
|
254001
|
+
obsPoints?.shape?.[0] === 3;
|
|
253777
254002
|
const modelMatrix2 = obsPointsModelMatrix?.clone();
|
|
253778
|
-
if (
|
|
253779
|
-
|
|
254003
|
+
if (obsPointsTilingType === "tiled") {
|
|
254004
|
+
return new TileLayer({
|
|
254005
|
+
id: `Tiled-${POINT_LAYER_PREFIX}${layerScope}`,
|
|
254006
|
+
coordinateSystem: COORDINATE_SYSTEM.CARTESIAN,
|
|
254007
|
+
// NOTE: picking is not working due to https://github.com/vitessce/vitessce/issues/2039
|
|
254008
|
+
modelMatrix: modelMatrix2,
|
|
254009
|
+
pickable: true,
|
|
254010
|
+
autoHighlight: true,
|
|
254011
|
+
onHover: (info2) => delegateHover(info2, "point", layerScope),
|
|
254012
|
+
opacity: spatialLayerOpacity,
|
|
254013
|
+
visible: spatialLayerVisible,
|
|
254014
|
+
// Since points are tiled but not multi-resolution,
|
|
254015
|
+
// it provides no benefit to request tiles at different zoom levels.
|
|
254016
|
+
// TODO: Should this value be the same for
|
|
254017
|
+
// every dataset, or do we need to
|
|
254018
|
+
// adjust based on the extent/density of the
|
|
254019
|
+
// point data (and/or account for modelMatrix, etc)?
|
|
254020
|
+
maxZoom: -1,
|
|
254021
|
+
minZoom: -1,
|
|
254022
|
+
tileSize: 512,
|
|
254023
|
+
// refinementStrategy: 'no-overlap',
|
|
254024
|
+
getTileData: async (tileInfo) => {
|
|
254025
|
+
const { index: index2, signal, bbox: bbox2, zoom: zoom2 } = tileInfo;
|
|
254026
|
+
const { z: z2, x: x2, y: y2 } = index2;
|
|
254027
|
+
this.obsPointsLoadingStatus = {
|
|
254028
|
+
...this.obsPointsLoadingStatus,
|
|
254029
|
+
[`${layerScope}-${z2}-${x2}-${y2}`]: "loading"
|
|
254030
|
+
};
|
|
254031
|
+
setTiledPointsLoadingProgress(this.obsPointsLoadingStatus);
|
|
254032
|
+
signal.addEventListener("abort", () => {
|
|
254033
|
+
this.obsPointsLoadingStatus = {
|
|
254034
|
+
...this.obsPointsLoadingStatus,
|
|
254035
|
+
[`${layerScope}-${z2}-${x2}-${y2}`]: "aborted"
|
|
254036
|
+
};
|
|
254037
|
+
setTiledPointsLoadingProgress(this.obsPointsLoadingStatus);
|
|
254038
|
+
});
|
|
254039
|
+
const pointsInTile = await loadPointsInRect(bbox2, signal);
|
|
254040
|
+
this.obsPointsLoadingStatus = {
|
|
254041
|
+
...this.obsPointsLoadingStatus,
|
|
254042
|
+
[`${layerScope}-${z2}-${x2}-${y2}`]: "success"
|
|
254043
|
+
};
|
|
254044
|
+
setTiledPointsLoadingProgress(this.obsPointsLoadingStatus);
|
|
254045
|
+
return {
|
|
254046
|
+
src: pointsInTile.data,
|
|
254047
|
+
length: pointsInTile.shape?.[1] || 0
|
|
254048
|
+
};
|
|
254049
|
+
},
|
|
254050
|
+
renderSubLayers: (subLayerProps) => {
|
|
254051
|
+
const { bbox: bbox2, content: tileData } = subLayerProps.tile;
|
|
254052
|
+
const { left: left2, top: top2, right: right2, bottom: bottom2 } = bbox2;
|
|
254053
|
+
const hasFeatureIndicesMinMax = !showUnselected && Array.isArray(featureIndices) && featureIndices.length === 1;
|
|
254054
|
+
const FILTER_PLACEHOLDER = 0;
|
|
254055
|
+
const featureIndicesMinMax = hasFeatureIndicesMinMax ? [featureIndices[0], featureIndices[0]] : [FILTER_PLACEHOLDER, FILTER_PLACEHOLDER];
|
|
254056
|
+
return new ScatterplotLayer(subLayerProps, {
|
|
254057
|
+
bounds: [left2, top2, right2, bottom2],
|
|
254058
|
+
data: tileData,
|
|
254059
|
+
getRadius: 5,
|
|
254060
|
+
radiusMaxPixels: 3,
|
|
254061
|
+
// getPosition: d => d,
|
|
254062
|
+
// getFillColor: [255, 0, 0],
|
|
254063
|
+
getPosition: (object2, { data: data2, index: index2, target: target2 }) => {
|
|
254064
|
+
target2[0] = data2.src.x[index2];
|
|
254065
|
+
target2[1] = data2.src.y[index2];
|
|
254066
|
+
target2[2] = 0;
|
|
254067
|
+
return target2;
|
|
254068
|
+
},
|
|
254069
|
+
getFillColor,
|
|
254070
|
+
// TODO: Is the picking stuff needed here in the Sublayer, or in the parent TileLayer?
|
|
254071
|
+
pickable: true,
|
|
254072
|
+
autoHighlight: true,
|
|
254073
|
+
onHover: (info2) => delegateHover(info2, "point", layerScope),
|
|
254074
|
+
// Use GPU filtering to filter to only the points in the tile bounding box,
|
|
254075
|
+
// since the row groups may contain points from other tiles.
|
|
254076
|
+
// Note: this can be improved using filterCategories,
|
|
254077
|
+
// but it is not available until post-v9 deck.gl/extensions.
|
|
254078
|
+
filterRange: [[left2, right2], [top2, bottom2], featureIndicesMinMax],
|
|
254079
|
+
getFilterValue: hasFeatureIndicesMinMax ? (object2, { data: data2, index: index2 }) => [
|
|
254080
|
+
data2.src.x[index2],
|
|
254081
|
+
data2.src.y[index2],
|
|
254082
|
+
data2.src.featureIndices[index2]
|
|
254083
|
+
] : (object2, { data: data2, index: index2 }) => [
|
|
254084
|
+
data2.src.x[index2],
|
|
254085
|
+
data2.src.y[index2],
|
|
254086
|
+
FILTER_PLACEHOLDER
|
|
254087
|
+
],
|
|
254088
|
+
extensions: [
|
|
254089
|
+
new DataFilterExtension({ filterSize: 3 })
|
|
254090
|
+
],
|
|
254091
|
+
updateTriggers: {
|
|
254092
|
+
getFillColor: [
|
|
254093
|
+
showUnselected,
|
|
254094
|
+
featureColor,
|
|
254095
|
+
obsColorEncoding,
|
|
254096
|
+
spatialLayerColor,
|
|
254097
|
+
featureSelection,
|
|
254098
|
+
hasMultipleFeaturesSelected
|
|
254099
|
+
],
|
|
254100
|
+
getFilterValue: [hasFeatureIndicesMinMax, showUnselected, featureSelection],
|
|
254101
|
+
filterRange: [hasFeatureIndicesMinMax, showUnselected, featureSelection]
|
|
254102
|
+
}
|
|
254103
|
+
});
|
|
254104
|
+
},
|
|
254105
|
+
updateTriggers: {
|
|
254106
|
+
getTileData: [
|
|
254107
|
+
showUnselected,
|
|
254108
|
+
featureColor,
|
|
254109
|
+
obsColorEncoding,
|
|
254110
|
+
spatialLayerColor,
|
|
254111
|
+
featureSelection,
|
|
254112
|
+
hasMultipleFeaturesSelected
|
|
254113
|
+
]
|
|
254114
|
+
}
|
|
254115
|
+
/*
|
|
254116
|
+
onTileError: (error) => {
|
|
254117
|
+
|
|
254118
|
+
},
|
|
254119
|
+
onViewportLoad: (loadedTiles) => {
|
|
254120
|
+
// Called when all tiles in the current viewport are loaded.
|
|
254121
|
+
// An array of loaded Tile instances are passed as argument to this function.
|
|
254122
|
+
},
|
|
254123
|
+
*/
|
|
254124
|
+
});
|
|
253780
254125
|
}
|
|
253781
254126
|
return new ScatterplotLayer({
|
|
253782
254127
|
id: `${POINT_LAYER_PREFIX}${layerScope}`,
|
|
@@ -253803,16 +254148,7 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
|
|
|
253803
254148
|
getFillColor: [obsColorEncoding, staticColor],
|
|
253804
254149
|
getLineColor: [obsColorEncoding, staticColor]
|
|
253805
254150
|
},
|
|
253806
|
-
...
|
|
253807
|
-
// TODO: support targetT filtering as well.
|
|
253808
|
-
// TODO: allow filtering by Z coordinate (rather than slice index)
|
|
253809
|
-
// Reference: https://github.com/vitessce/vitessce/issues/2194
|
|
253810
|
-
filterRange: [targetZ, targetZ],
|
|
253811
|
-
getFilterValue: (object2, { data: data2, index: index2 }) => data2.src.obsPoints.data[2][index2],
|
|
253812
|
-
extensions: [
|
|
253813
|
-
new DataFilterExtension({ filterSize: 1 })
|
|
253814
|
-
]
|
|
253815
|
-
} : {}
|
|
254151
|
+
...{}
|
|
253816
254152
|
});
|
|
253817
254153
|
}
|
|
253818
254154
|
createSelectionLayer() {
|
|
@@ -254352,28 +254688,45 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
|
|
|
254352
254688
|
}
|
|
254353
254689
|
onUpdatePointsData(layerScope) {
|
|
254354
254690
|
const { obsPoints, pointMultiObsLabels } = this.props;
|
|
254355
|
-
const { obsIndex, obsPoints: layerObsPoints, obsPointsModelMatrix } = obsPoints?.[layerScope] || {};
|
|
254691
|
+
const { obsIndex, obsPoints: layerObsPoints, obsPointsModelMatrix, loadPointsInRect, obsPointsTilingType } = obsPoints?.[layerScope] || {};
|
|
254356
254692
|
const { obsIndex: obsLabelsIndex, obsLabels } = pointMultiObsLabels?.[layerScope] || {};
|
|
254357
|
-
if (
|
|
254358
|
-
const getCellCoords = makeDefaultGetObsCoords(layerObsPoints);
|
|
254359
|
-
this.obsPointsQuadTree[layerScope] = createQuadTree(layerObsPoints, getCellCoords);
|
|
254693
|
+
if (obsPointsTilingType === "tiled") {
|
|
254360
254694
|
this.obsPointsData[layerScope] = {
|
|
254361
254695
|
src: {
|
|
254362
|
-
|
|
254363
|
-
|
|
254696
|
+
obsPointsTilingType,
|
|
254697
|
+
obsIndex: null,
|
|
254698
|
+
obsPoints: null,
|
|
254364
254699
|
obsPointsModelMatrix,
|
|
254365
254700
|
obsLabelsMap: null,
|
|
254366
254701
|
uniqueObsLabels: null,
|
|
254367
|
-
PALETTE: null
|
|
254702
|
+
PALETTE: null,
|
|
254703
|
+
loadPointsInRect
|
|
254368
254704
|
},
|
|
254369
|
-
length:
|
|
254705
|
+
length: null
|
|
254370
254706
|
};
|
|
254371
|
-
|
|
254372
|
-
|
|
254373
|
-
const
|
|
254374
|
-
this.
|
|
254375
|
-
this.obsPointsData[layerScope]
|
|
254376
|
-
|
|
254707
|
+
} else {
|
|
254708
|
+
if (layerObsPoints) {
|
|
254709
|
+
const getCellCoords = makeDefaultGetObsCoords(layerObsPoints);
|
|
254710
|
+
this.obsPointsQuadTree[layerScope] = createQuadTree(layerObsPoints, getCellCoords);
|
|
254711
|
+
this.obsPointsData[layerScope] = {
|
|
254712
|
+
src: {
|
|
254713
|
+
obsPointsTilingType,
|
|
254714
|
+
obsIndex,
|
|
254715
|
+
obsPoints: layerObsPoints,
|
|
254716
|
+
obsPointsModelMatrix,
|
|
254717
|
+
obsLabelsMap: null,
|
|
254718
|
+
uniqueObsLabels: null,
|
|
254719
|
+
PALETTE: null
|
|
254720
|
+
},
|
|
254721
|
+
length: layerObsPoints.shape[1]
|
|
254722
|
+
};
|
|
254723
|
+
if (obsLabels) {
|
|
254724
|
+
const obsLabelsMap = new Map(obsLabelsIndex.map((key2, i2) => [key2, obsLabels[i2]]));
|
|
254725
|
+
const uniqueObsLabels = Array.from(new Set(obsLabels));
|
|
254726
|
+
this.obsPointsData[layerScope].src.obsLabelsMap = obsLabelsMap;
|
|
254727
|
+
this.obsPointsData[layerScope].src.uniqueObsLabels = uniqueObsLabels;
|
|
254728
|
+
this.obsPointsData[layerScope].src.PALETTE = PALETTE;
|
|
254729
|
+
}
|
|
254377
254730
|
}
|
|
254378
254731
|
}
|
|
254379
254732
|
}
|
|
@@ -254582,6 +254935,7 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
|
|
|
254582
254935
|
// Data props.
|
|
254583
254936
|
"obsPoints",
|
|
254584
254937
|
"pointMultiObsLabels",
|
|
254938
|
+
"pointMatrixIndices",
|
|
254585
254939
|
// Coordination props.
|
|
254586
254940
|
"pointLayerScopes",
|
|
254587
254941
|
"pointLayerCoordination"
|
|
@@ -254736,12 +255090,12 @@ class ErrorBoundary extends React__default.Component {
|
|
|
254736
255090
|
}
|
|
254737
255091
|
}
|
|
254738
255092
|
const LazySpatialThree = React__default.lazy(async () => {
|
|
254739
|
-
const { SpatialWrapper: SpatialWrapper2 } = await import("./index-
|
|
255093
|
+
const { SpatialWrapper: SpatialWrapper2 } = await import("./index-C1eGTlSq.js");
|
|
254740
255094
|
return { default: SpatialWrapper2 };
|
|
254741
255095
|
});
|
|
254742
255096
|
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 }) }) }) }));
|
|
254743
255097
|
const LazySpatialAccelerated = React__default.lazy(async () => {
|
|
254744
|
-
const { SpatialWrapper: SpatialWrapper2 } = await import("./index-
|
|
255098
|
+
const { SpatialWrapper: SpatialWrapper2 } = await import("./index-DHvGxl1H.js");
|
|
254745
255099
|
return { default: SpatialWrapper2 };
|
|
254746
255100
|
});
|
|
254747
255101
|
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 }) }) }) }));
|
|
@@ -254856,12 +255210,22 @@ const DEFAULT_VIEW_STATE = {
|
|
|
254856
255210
|
const SET_VIEW_STATE_NOOP = () => {
|
|
254857
255211
|
};
|
|
254858
255212
|
function getHoverData(hoverInfo, layerType) {
|
|
254859
|
-
const { coordinate, sourceLayer: layer, tile } = hoverInfo;
|
|
254860
|
-
if (layerType === "segmentation-bitmask" || layerType === "image") {
|
|
255213
|
+
const { coordinate, sourceLayer: layer, tile, index: pointIndex } = hoverInfo;
|
|
255214
|
+
if (layerType === "segmentation-bitmask" || layerType === "image" || layerType === "point") {
|
|
254861
255215
|
if (coordinate && layer) {
|
|
254862
255216
|
if (layer.id.startsWith("Tiled") && tile) {
|
|
254863
255217
|
const { content: content2, bbox: bbox2, index: { z: z2 } } = tile;
|
|
254864
255218
|
if (content2) {
|
|
255219
|
+
if (layerType === "point" && pointIndex >= 0) {
|
|
255220
|
+
const { src } = content2 || {};
|
|
255221
|
+
const { x: x2, y: y2, featureIndices } = src || {};
|
|
255222
|
+
return {
|
|
255223
|
+
pointIndex,
|
|
255224
|
+
x: x2?.[pointIndex],
|
|
255225
|
+
y: y2?.[pointIndex],
|
|
255226
|
+
featureIndex: featureIndices?.[pointIndex]
|
|
255227
|
+
};
|
|
255228
|
+
}
|
|
254865
255229
|
const { data: data2, width: width2, height: height2 } = content2;
|
|
254866
255230
|
const { left: left2, right: right2, top: top2, bottom: bottom2 } = bbox2;
|
|
254867
255231
|
const bounds2 = [
|
|
@@ -255039,6 +255403,8 @@ function SpatialSubscriber(props) {
|
|
|
255039
255403
|
CoordinationType$1.SPATIAL_LAYER_VISIBLE,
|
|
255040
255404
|
CoordinationType$1.SPATIAL_LAYER_OPACITY,
|
|
255041
255405
|
CoordinationType$1.OBS_COLOR_ENCODING,
|
|
255406
|
+
CoordinationType$1.FEATURE_COLOR,
|
|
255407
|
+
CoordinationType$1.FEATURE_FILTER_MODE,
|
|
255042
255408
|
CoordinationType$1.FEATURE_SELECTION,
|
|
255043
255409
|
CoordinationType$1.FEATURE_VALUE_COLORMAP,
|
|
255044
255410
|
CoordinationType$1.FEATURE_VALUE_COLORMAP_RANGE,
|
|
@@ -255049,7 +255415,10 @@ function SpatialSubscriber(props) {
|
|
|
255049
255415
|
CoordinationType$1.LEGEND_VISIBLE
|
|
255050
255416
|
], coordinationScopes, coordinationScopesBy, CoordinationType$1.POINT_LAYER);
|
|
255051
255417
|
const [volumeLoadingStatus, setVolumeLoadingStatus] = useState(null);
|
|
255052
|
-
const [{ volumeLoadingProgress }, { setVolumeLoadingProgress }] = useAuxiliaryCoordination([
|
|
255418
|
+
const [{ volumeLoadingProgress, tiledPointsLoadingProgress }, { setVolumeLoadingProgress, setTiledPointsLoadingProgress }] = useAuxiliaryCoordination([
|
|
255419
|
+
"spatialAcceleratedVolumeLoadingProgress",
|
|
255420
|
+
"spatialTiledPointsLoadingProgress"
|
|
255421
|
+
], coordinationScopes);
|
|
255053
255422
|
useEffect(() => {
|
|
255054
255423
|
if (volumeLoadingStatus && volumeLoadingStatus.loadingProgress) {
|
|
255055
255424
|
setVolumeLoadingProgress(volumeLoadingStatus);
|
|
@@ -255066,6 +255435,7 @@ function SpatialSubscriber(props) {
|
|
|
255066
255435
|
const height2 = threeFor3d && deckHeight === void 0 ? threeHeight : deckHeight;
|
|
255067
255436
|
const [obsPointsData, obsPointsDataStatus, obsPointsUrls, obsPointsErrors] = useMultiObsPoints(coordinationScopes, coordinationScopesBy, loaders, dataset, mergeCoordination, uuid2);
|
|
255068
255437
|
const [pointMultiObsLabelsData, pointMultiObsLabelsDataStatus, pointMultiObsLabelsErrors] = usePointMultiObsLabels(coordinationScopes, coordinationScopesBy, loaders, dataset);
|
|
255438
|
+
const [pointMultiIndicesData, pointMultiIndicesDataStatus, pointMultiIndicesDataErrors] = usePointMultiObsFeatureMatrixIndices(coordinationScopes, coordinationScopesBy, loaders, dataset);
|
|
255069
255439
|
const [obsSpotsData, obsSpotsDataStatus, obsSpotsUrls, obsSpotsErrors] = useMultiObsSpots(coordinationScopes, coordinationScopesBy, loaders, dataset, mergeCoordination, uuid2);
|
|
255070
255440
|
const [obsSpotsSetsData, obsSpotsSetsDataStatus, obsSpotSetsUrls, obsSpotsSetsErrors] = useSpotMultiObsSets(coordinationScopes, coordinationScopesBy, loaders, dataset);
|
|
255071
255441
|
const [obsSpotsFeatureLabelsData, obsSpotsFeatureLabelsDataStatus, obsSpotsFeatureLabelsUrls, obsSpotsFeatureLabelsErrors] = useSpotMultiFeatureLabels(coordinationScopes, coordinationScopesBy, loaders, dataset);
|
|
@@ -255099,6 +255469,7 @@ function SpatialSubscriber(props) {
|
|
|
255099
255469
|
...spotMultiFeatureSelectionErrors,
|
|
255100
255470
|
...spotMultiIndicesDataErrors,
|
|
255101
255471
|
...pointMultiObsLabelsErrors,
|
|
255472
|
+
...pointMultiIndicesDataErrors,
|
|
255102
255473
|
...segmentationMultiFeatureSelectionErrors,
|
|
255103
255474
|
...segmentationMultiIndicesDataErrors,
|
|
255104
255475
|
...obsSegmentationsLocationsDataErrors
|
|
@@ -255118,6 +255489,7 @@ function SpatialSubscriber(props) {
|
|
|
255118
255489
|
// Points
|
|
255119
255490
|
obsPointsDataStatus,
|
|
255120
255491
|
pointMultiObsLabelsDataStatus,
|
|
255492
|
+
pointMultiIndicesDataStatus,
|
|
255121
255493
|
// Segmentations
|
|
255122
255494
|
obsSegmentationsDataStatus,
|
|
255123
255495
|
obsSegmentationsSetsDataStatus,
|
|
@@ -255305,14 +255677,19 @@ function SpatialSubscriber(props) {
|
|
|
255305
255677
|
pointLayerScopes?.forEach((pointLayerScope) => {
|
|
255306
255678
|
const { setObsHighlight } = pointLayerCoordination?.[1]?.[pointLayerScope] || {};
|
|
255307
255679
|
if (hoverData && layerType === "point" && layerScope === pointLayerScope) {
|
|
255308
|
-
|
|
255309
|
-
const { obsIndex } = obsPointsData?.[pointLayerScope] || {};
|
|
255310
|
-
const obsId = obsIndex?.[obsI];
|
|
255311
|
-
if (obsIndex && obsId) {
|
|
255680
|
+
if (typeof hoverData === "object" && hoverData?.pointIndex) {
|
|
255312
255681
|
showAnyTooltip = true;
|
|
255313
|
-
setObsHighlight(
|
|
255682
|
+
setObsHighlight(hoverData.pointIndex);
|
|
255314
255683
|
} else {
|
|
255315
|
-
|
|
255684
|
+
const obsI = hoverData;
|
|
255685
|
+
const { obsIndex } = obsPointsData?.[pointLayerScope] || {};
|
|
255686
|
+
const obsId = obsIndex?.[obsI];
|
|
255687
|
+
if (obsIndex && obsId) {
|
|
255688
|
+
showAnyTooltip = true;
|
|
255689
|
+
setObsHighlight(obsId);
|
|
255690
|
+
} else {
|
|
255691
|
+
setObsHighlight(null);
|
|
255692
|
+
}
|
|
255316
255693
|
}
|
|
255317
255694
|
} else {
|
|
255318
255695
|
setObsHighlight(null);
|
|
@@ -255354,7 +255731,7 @@ function SpatialSubscriber(props) {
|
|
|
255354
255731
|
target: [targetX2, targetY2, targetZ],
|
|
255355
255732
|
rotationX,
|
|
255356
255733
|
rotationOrbit
|
|
255357
|
-
} : DEFAULT_VIEW_STATE, orbitAxis, spatialAxisFixed, setViewState: isValidViewState ? setViewState : SET_VIEW_STATE_NOOP, originalViewState, spatialRenderingMode, updateViewInfo: setComponentViewInfo, delegateHover, obsPoints: obsPointsData, pointLayerScopes, pointLayerCoordination, pointMultiObsLabels: pointMultiObsLabelsData, 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 }), !disableTooltip && jsxRuntimeExports.jsx(SpatialTooltipSubscriber, {
|
|
255734
|
+
} : 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 }), !disableTooltip && jsxRuntimeExports.jsx(SpatialTooltipSubscriber, {
|
|
255358
255735
|
parentUuid: uuid2,
|
|
255359
255736
|
width: width2,
|
|
255360
255737
|
height: height2,
|
|
@@ -255395,7 +255772,8 @@ function SpatialSubscriber(props) {
|
|
|
255395
255772
|
spotMultiFeatureLabels: obsSpotsFeatureLabelsData,
|
|
255396
255773
|
// Points
|
|
255397
255774
|
pointLayerScopes,
|
|
255398
|
-
pointLayerCoordination
|
|
255775
|
+
pointLayerCoordination,
|
|
255776
|
+
pointMultiIndicesData
|
|
255399
255777
|
}
|
|
255400
255778
|
), jsxRuntimeExports.jsx(
|
|
255401
255779
|
ChannelNamesLegend,
|
|
@@ -264357,17 +264735,35 @@ function SpotLayerController(props) {
|
|
|
264357
264735
|
return jsxRuntimeExports.jsx(Grid$1, { className: lcClasses.layerControllerGrid, children: jsxRuntimeExports.jsx(Paper, { elevation: 4, className: lcClasses.layerControllerRoot, children: jsxRuntimeExports.jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsxRuntimeExports.jsx(Grid$1, { size: 1, children: jsxRuntimeExports.jsx(Button, { onClick: handleVisibleChange, className: menuClasses.imageLayerVisibleButton, "aria-label": "Toggle spot layer visibility", children: jsxRuntimeExports.jsx(Visibility, {}) }) }), jsxRuntimeExports.jsx(Grid$1, { size: 1, children: jsxRuntimeExports.jsx(ChannelColorPickerMenu, { theme, color: color2, setColor: setColor2, palette, isStaticColor, isColormap, featureValueColormap, visible }) }), jsxRuntimeExports.jsx(Grid$1, { size: 6, children: jsxRuntimeExports.jsx(Typography, { className: menuClasses.imageLayerName, children: label2 }) }), jsxRuntimeExports.jsx(Grid$1, { size: 2, children: jsxRuntimeExports.jsx(Slider, { value: opacity2, min: 0, max: 1, step: 1e-3, onChange: handleOpacityChange, className: menuClasses.imageLayerOpacitySlider, orientation: "horizontal", "aria-label": `Adjust opacity for layer ${label2}` }) }), jsxRuntimeExports.jsx(Grid$1, { size: 1, children: jsxRuntimeExports.jsx(SpotLayerEllipsisMenu, { filled, setFilled, strokeWidth, setStrokeWidth, featureSelection, obsColorEncoding, setObsColorEncoding, featureValueColormap, setFeatureValueColormap, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible }) }), jsxRuntimeExports.jsx(Grid$1, { size: 1, children: jsxRuntimeExports.jsx(SvgSpots, { className: classes2.layerTypeSpotIcon }) })] }) }) });
|
|
264358
264736
|
}
|
|
264359
264737
|
const useStyles$f = makeStyles()(() => ({
|
|
264738
|
+
pointLayerButton: {
|
|
264739
|
+
borderStyle: "dashed",
|
|
264740
|
+
marginTop: "10px",
|
|
264741
|
+
marginBottom: "10px",
|
|
264742
|
+
fontWeight: 400
|
|
264743
|
+
},
|
|
264744
|
+
pointFeatureControllerGrid: {
|
|
264745
|
+
padding: "0",
|
|
264746
|
+
flexWrap: "nowrap"
|
|
264747
|
+
},
|
|
264748
|
+
pointFeatureExpansionButton: {
|
|
264749
|
+
display: "inline-block",
|
|
264750
|
+
margin: 0,
|
|
264751
|
+
padding: 0,
|
|
264752
|
+
minWidth: 0,
|
|
264753
|
+
lineHeight: 1,
|
|
264754
|
+
width: "50%"
|
|
264755
|
+
},
|
|
264360
264756
|
layerTypePointIcon: {
|
|
264361
264757
|
height: "100%",
|
|
264362
|
-
|
|
264758
|
+
paddingLeft: "2px",
|
|
264363
264759
|
fill: "currentColor",
|
|
264364
|
-
fontSize: "
|
|
264760
|
+
fontSize: "14px",
|
|
264365
264761
|
width: "50%",
|
|
264366
|
-
maxWidth: "
|
|
264762
|
+
maxWidth: "16px"
|
|
264367
264763
|
}
|
|
264368
264764
|
}));
|
|
264369
264765
|
function PointLayerEllipsisMenu(props) {
|
|
264370
|
-
const { featureSelection, obsColorEncoding, setObsColorEncoding, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible } = props;
|
|
264766
|
+
const { featureSelection, featureFilterMode, setFeatureFilterMode, obsColorEncoding, setObsColorEncoding, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible } = props;
|
|
264371
264767
|
const [open2, setOpen] = useState(false);
|
|
264372
264768
|
const { classes: selectClasses2 } = useSelectStyles();
|
|
264373
264769
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
@@ -264376,17 +264772,84 @@ function PointLayerEllipsisMenu(props) {
|
|
|
264376
264772
|
const tooltipsVisibleId = $bdb11010cef70236$export$f680877a34711e37();
|
|
264377
264773
|
const crosshairsVisibleId = $bdb11010cef70236$export$f680877a34711e37();
|
|
264378
264774
|
const legendVisibleId = $bdb11010cef70236$export$f680877a34711e37();
|
|
264379
|
-
|
|
264775
|
+
const featureFilterModeId = $bdb11010cef70236$export$f680877a34711e37();
|
|
264776
|
+
return jsxRuntimeExports.jsxs(PopperMenu, { open: open2, setOpen, buttonIcon: jsxRuntimeExports.jsx(MoreVertIcon, {}), buttonClassName: menuClasses.imageLayerMenuButton, containerClassName: menuClasses.imageLayerPopperContainer, withPaper: true, "aria-label": "Open point layer options menu", children: [jsxRuntimeExports.jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsxRuntimeExports.jsx("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: quantitativeColormapId, children: "Color Encoding: " }), jsxRuntimeExports.jsxs(NativeSelect, { onChange: (e3) => setObsColorEncoding(e3.target.value), value: obsColorEncoding, inputProps: { id: quantitativeColormapId, "aria-label": "Color encoding selector" }, classes: { root: selectClasses2.selectRoot }, children: [jsxRuntimeExports.jsx("option", { value: "spatialLayerColor", children: "Static Color" }), jsxRuntimeExports.jsx("option", { value: "geneSelection", children: "Feature Color" }), jsxRuntimeExports.jsx("option", { value: "randomByFeature", children: "Random Color per Feature" }), jsxRuntimeExports.jsx("option", { value: "random", children: "Random Color per Point" })] })] }), jsxRuntimeExports.jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsxRuntimeExports.jsx("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: featureFilterModeId, children: "Filter to Feature Selection: " }), jsxRuntimeExports.jsx(Checkbox$1, { color: "primary", className: menuClasses.menuItemCheckbox, checked: featureFilterMode === "featureSelection", onChange: (e3, v) => setFeatureFilterMode(v ? "featureSelection" : null), slotProps: { input: { id: featureFilterModeId, "aria-label": "Toggle feature filter mode" } } })] }), jsxRuntimeExports.jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsxRuntimeExports.jsx("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: colormapRangeId, children: "Colormap Range: " }), jsxRuntimeExports.jsx(Slider, { disabled: obsColorEncoding !== "geneSelection", value: featureValueColormapRange, min: 0, max: 1, step: 0.01, onChange: (e3, v) => setFeatureValueColormapRange(v), className: menuClasses.menuItemSlider, orientation: "horizontal", id: colormapRangeId, getAriaLabel: (index2) => index2 === 0 ? "Low value colormap range slider" : "High value colormap range slider" })] }), jsxRuntimeExports.jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsxRuntimeExports.jsx("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: tooltipsVisibleId, children: "Tooltips Visible: " }), jsxRuntimeExports.jsx(Checkbox$1, { color: "primary", className: menuClasses.menuItemCheckbox, checked: tooltipsVisible, onChange: (e3, v) => setTooltipsVisible(v), slotProps: { input: { id: tooltipsVisibleId, "aria-label": "Toggle tooltip visibility" } } })] }), jsxRuntimeExports.jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsxRuntimeExports.jsx("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: crosshairsVisibleId, children: "Tooltip Crosshairs Visible: " }), jsxRuntimeExports.jsx(Checkbox$1, { color: "primary", className: menuClasses.menuItemCheckbox, checked: tooltipCrosshairsVisible, onChange: (e3, v) => setTooltipCrosshairsVisible(v), slotProps: { input: { id: crosshairsVisibleId, "aria-label": "Toggle tooltip crosshair visibility" } } })] }), jsxRuntimeExports.jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsxRuntimeExports.jsx("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: legendVisibleId, children: "Legend Visible: " }), jsxRuntimeExports.jsx(Checkbox$1, { color: "primary", className: menuClasses.menuItemCheckbox, checked: legendVisible, onChange: (e3, v) => setLegendVisible(v), slotProps: { input: { id: legendVisibleId, "aria-label": "Toggle legend visibility" } } })] })] });
|
|
264380
264777
|
}
|
|
264381
264778
|
function PointLayerController(props) {
|
|
264382
|
-
const { theme, layerScope, layerCoordination, setLayerCoordination, palette = null } = props;
|
|
264383
|
-
const
|
|
264384
|
-
const
|
|
264779
|
+
const { theme, layerScope, layerCoordination, setLayerCoordination, palette = null, pointMatrixIndicesData, tiledPointsLoadingProgress } = props;
|
|
264780
|
+
const [open2, setOpen] = useState(false);
|
|
264781
|
+
const loadingDoneFraction = useMemo$1(() => {
|
|
264782
|
+
if (tiledPointsLoadingProgress && typeof tiledPointsLoadingProgress === "object") {
|
|
264783
|
+
return 1 - Object.values(tiledPointsLoadingProgress).filter((status) => status === "loading").length / Object.values(tiledPointsLoadingProgress).length;
|
|
264784
|
+
}
|
|
264785
|
+
return 1;
|
|
264786
|
+
}, [tiledPointsLoadingProgress]);
|
|
264787
|
+
const { obsType, spatialLayerVisible: visible, spatialLayerOpacity: opacity2, obsColorEncoding, featureColor, featureFilterMode, featureSelection, featureValueColormap, featureValueColormapRange, spatialLayerColor, tooltipsVisible, tooltipCrosshairsVisible, legendVisible } = layerCoordination;
|
|
264788
|
+
const { setSpatialLayerVisible: setVisible, setSpatialLayerOpacity: setOpacity2, setObsColorEncoding, setFeatureColor, setFeatureFilterMode, setFeatureSelection, setFeatureValueColormap, setFeatureValueColormapRange, setSpatialLayerColor, setTooltipsVisible, setTooltipCrosshairsVisible, setLegendVisible } = setLayerCoordination;
|
|
264385
264789
|
const label2 = capitalize$3(obsType);
|
|
264386
264790
|
const visibleSetting = typeof visible === "boolean" ? visible : true;
|
|
264387
264791
|
const Visibility = useMemo$1(() => visibleSetting ? VisibilityIcon : VisibilityOffIcon, [visibleSetting]);
|
|
264388
|
-
const
|
|
264389
|
-
|
|
264792
|
+
const hasUnspecifiedFeatureColors = useMemo$1(() => {
|
|
264793
|
+
if (Array.isArray(featureSelection)) {
|
|
264794
|
+
if (Array.isArray(featureColor)) {
|
|
264795
|
+
return featureSelection.some((featureName) => {
|
|
264796
|
+
const colorForFeature = featureColor.find((fc) => fc.name === featureName);
|
|
264797
|
+
return !colorForFeature;
|
|
264798
|
+
});
|
|
264799
|
+
}
|
|
264800
|
+
return featureSelection.length > 0;
|
|
264801
|
+
}
|
|
264802
|
+
return true;
|
|
264803
|
+
}, [featureColor, featureSelection]);
|
|
264804
|
+
const isStaticColor = obsColorEncoding === "spatialLayerColor" || obsColorEncoding === "geneSelection";
|
|
264805
|
+
const showStaticColor = obsColorEncoding === "spatialLayerColor" || obsColorEncoding === "geneSelection" && hasUnspecifiedFeatureColors;
|
|
264806
|
+
const isColormap = false;
|
|
264807
|
+
const hasSingleSelectedFeature = obsColorEncoding === "geneSelection" && Array.isArray(featureSelection) && featureSelection.length === 1;
|
|
264808
|
+
const color2 = useMemo$1(() => {
|
|
264809
|
+
if (showStaticColor) {
|
|
264810
|
+
return spatialLayerColor;
|
|
264811
|
+
}
|
|
264812
|
+
if (hasSingleSelectedFeature) {
|
|
264813
|
+
const selectedFeatureColor = featureColor?.find((fc) => fc.name === featureSelection[0])?.color;
|
|
264814
|
+
if (selectedFeatureColor) {
|
|
264815
|
+
return selectedFeatureColor;
|
|
264816
|
+
}
|
|
264817
|
+
}
|
|
264818
|
+
return null;
|
|
264819
|
+
}, [
|
|
264820
|
+
hasSingleSelectedFeature,
|
|
264821
|
+
spatialLayerColor,
|
|
264822
|
+
featureColor,
|
|
264823
|
+
featureSelection,
|
|
264824
|
+
showStaticColor
|
|
264825
|
+
]);
|
|
264826
|
+
const setColor2 = useCallback((newColor) => {
|
|
264827
|
+
if (showStaticColor) {
|
|
264828
|
+
setSpatialLayerColor(newColor);
|
|
264829
|
+
} else if (hasSingleSelectedFeature) {
|
|
264830
|
+
const featureColorIndex = featureColor?.findIndex((fc) => fc.name === featureSelection[0]);
|
|
264831
|
+
if (featureColorIndex !== void 0 && featureColorIndex >= 0) {
|
|
264832
|
+
const newFeatureColor = [...featureColor];
|
|
264833
|
+
newFeatureColor[featureColorIndex] = {
|
|
264834
|
+
name: featureSelection[0],
|
|
264835
|
+
color: newColor
|
|
264836
|
+
};
|
|
264837
|
+
setFeatureColor(newFeatureColor);
|
|
264838
|
+
} else {
|
|
264839
|
+
setFeatureColor([
|
|
264840
|
+
...featureColor,
|
|
264841
|
+
{ name: featureSelection[0], color: newColor }
|
|
264842
|
+
]);
|
|
264843
|
+
}
|
|
264844
|
+
}
|
|
264845
|
+
}, [
|
|
264846
|
+
hasSingleSelectedFeature,
|
|
264847
|
+
setSpatialLayerColor,
|
|
264848
|
+
featureColor,
|
|
264849
|
+
setFeatureColor,
|
|
264850
|
+
featureSelection,
|
|
264851
|
+
showStaticColor
|
|
264852
|
+
]);
|
|
264390
264853
|
const { classes: classes2 } = useStyles$f();
|
|
264391
264854
|
const { classes: lcClasses } = useControllerSectionStyles();
|
|
264392
264855
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
@@ -264395,7 +264858,10 @@ function PointLayerController(props) {
|
|
|
264395
264858
|
setVisible(nextVisible);
|
|
264396
264859
|
}, [visible, setVisible]);
|
|
264397
264860
|
const handleOpacityChange = useCallback((e3, v) => setOpacity2(v), [setOpacity2]);
|
|
264398
|
-
|
|
264861
|
+
useCallback(() => setOpen((prev2) => !prev2), []);
|
|
264862
|
+
const [coloringTabIndex, setColoringTabIndex] = useState(0);
|
|
264863
|
+
const { featureIndex } = pointMatrixIndicesData || {};
|
|
264864
|
+
return jsxRuntimeExports.jsx(Grid$1, { className: lcClasses.layerControllerGrid, children: jsxRuntimeExports.jsxs(Paper, { elevation: 4, className: lcClasses.layerControllerRoot, children: [jsxRuntimeExports.jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsxRuntimeExports.jsx(Grid$1, { size: 1, children: jsxRuntimeExports.jsx(Button, { onClick: handleVisibleChange, className: menuClasses.imageLayerVisibleButton, "aria-label": "Toggle layer visibility", children: jsxRuntimeExports.jsx(Visibility, {}) }) }), jsxRuntimeExports.jsx(Grid$1, { size: 1, children: jsxRuntimeExports.jsx(ChannelColorPickerMenu, { theme, color: color2, setColor: setColor2, palette, isStaticColor, isColormap, featureValueColormap, visible }) }), jsxRuntimeExports.jsx(Grid$1, { size: 6, children: jsxRuntimeExports.jsx(Typography, { className: menuClasses.imageLayerName, children: label2 }) }), jsxRuntimeExports.jsx(Grid$1, { size: 2, children: jsxRuntimeExports.jsx(Slider, { value: opacity2, min: 0, max: 1, step: 1e-3, onChange: handleOpacityChange, className: menuClasses.imageLayerOpacitySlider, orientation: "horizontal", "aria-label": `Adjust opacity for layer ${label2}` }) }), jsxRuntimeExports.jsx(Grid$1, { size: 1, children: jsxRuntimeExports.jsx(PointLayerEllipsisMenu, { featureSelection, obsColorEncoding, setObsColorEncoding, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible, featureFilterMode, setFeatureFilterMode }) }), jsxRuntimeExports.jsxs(Grid$1, { size: 1, container: true, direction: "row", children: [jsxRuntimeExports.jsx(SvgPoints, { className: classes2.layerTypePointIcon }), null] })] }), loadingDoneFraction < 1 ? jsxRuntimeExports.jsx(Grid$1, { size: 12, container: true, direction: "column", justifyContent: "space-between", className: classes2.pointFeatureControllerGrid, children: jsxRuntimeExports.jsx(LinearProgress, { variant: loadingDoneFraction === 0 ? "indeterminate" : "determinate", value: loadingDoneFraction * 100 }) }) : null, null] }) });
|
|
264399
264865
|
}
|
|
264400
264866
|
const useStyles$e = makeStyles()(() => ({
|
|
264401
264867
|
layerTypeSegmentationIcon: {
|
|
@@ -267403,7 +267869,7 @@ function ImageLayerEllipsisMenu(props) {
|
|
|
267403
267869
|
const { classes: selectClasses2 } = useSelectStyles();
|
|
267404
267870
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
267405
267871
|
const [localLodSliderValue, setLocalLodSliderValue] = useState(convertLodFactorToLogarithmicSliderValue(spatialLodFactor || 1));
|
|
267406
|
-
|
|
267872
|
+
useEffect(() => {
|
|
267407
267873
|
setLocalLodSliderValue(convertLodFactorToLogarithmicSliderValue(spatialLodFactor || 1));
|
|
267408
267874
|
}, [spatialLodFactor]);
|
|
267409
267875
|
const is3dMode = spatialRenderingMode === "3D";
|
|
@@ -267539,7 +268005,7 @@ function GlobalDimensionSlider(props) {
|
|
|
267539
268005
|
return jsxRuntimeExports.jsx(Grid$1, { className: lcClasses.layerControllerGrid, children: jsxRuntimeExports.jsx(Paper, { elevation: 4, className: lcClasses.layerControllerRoot, children: jsxRuntimeExports.jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsxRuntimeExports.jsx(Grid$1, { size: 1, children: jsxRuntimeExports.jsx(SvgDimensions, { className: classes2.dimensionsIcon }) }), jsxRuntimeExports.jsx(Grid$1, { size: 1, children: jsxRuntimeExports.jsx(Typography, { className: classes2.dimensionLabel, children: label2 }) }), jsxRuntimeExports.jsx(Grid$1, { size: 8, children: jsxRuntimeExports.jsx(Slider, { value: targetValue, min: min2, max: max2, step: 1, onChange: (e3, v) => setTargetValue(v), className: classes2.dimensionSlider, valueLabelDisplay: "auto", orientation: "horizontal", disabled: spatialRenderingMode === "3D", "aria-label": `${label2}-slice slider` }) }), jsxRuntimeExports.jsx(Grid$1, { size: 2, children: isForZ ? jsxRuntimeExports.jsx(FormGroup, { row: true, className: classes2.switchFormGroup, children: jsxRuntimeExports.jsx(FormControlLabel$1, { control: jsxRuntimeExports.jsx(Switch, { color: "primary", checked: spatialRenderingMode === "3D", onChange: handleRenderingModeChange, name: "is3dMode" }), label: "3D" }) }) : null })] }) }) });
|
|
267540
268006
|
}
|
|
267541
268007
|
function LayerController(props) {
|
|
267542
|
-
const { theme, coordinationScopesRaw, segmentationLayerScopes, segmentationLayerCoordination, segmentationChannelScopesByLayer, segmentationChannelCoordination, images, imageLayerScopes, imageLayerCoordination, targetT, targetZ, setTargetT, setTargetZ, spatialRenderingMode, setSpatialRenderingMode, imageChannelScopesByLayer, imageChannelCoordination, spotLayerScopes, spotLayerCoordination, pointLayerScopes, pointLayerCoordination, volumeLoadingStatus } = props;
|
|
268008
|
+
const { theme, coordinationScopesRaw, segmentationLayerScopes, segmentationLayerCoordination, segmentationChannelScopesByLayer, segmentationChannelCoordination, images, imageLayerScopes, imageLayerCoordination, targetT, targetZ, setTargetT, setTargetZ, spatialRenderingMode, setSpatialRenderingMode, imageChannelScopesByLayer, imageChannelCoordination, spotLayerScopes, spotLayerCoordination, pointLayerScopes, pointLayerCoordination, pointMultiIndicesData, volumeLoadingStatus, tiledPointsLoadingProgress } = props;
|
|
267543
268009
|
const anyLayerHasT = Object.values(images || {}).some((image2) => image2?.image?.instance.hasTStack());
|
|
267544
268010
|
const anyLayerHasZ = Object.values(images || {}).some((image2) => image2?.image?.instance.hasZStack());
|
|
267545
268011
|
const maxT = Object.values(images || {}).reduce((a2, h2) => Math.max(a2, h2?.image?.instance.getNumT()), 1) - 1;
|
|
@@ -267548,7 +268014,7 @@ function LayerController(props) {
|
|
|
267548
268014
|
const reversedSegmentationLayerScopes = useMemo$1(() => [...segmentationLayerScopes || []].reverse(), [segmentationLayerScopes]);
|
|
267549
268015
|
const reversedSpotLayerScopes = useMemo$1(() => [...spotLayerScopes || []].reverse(), [spotLayerScopes]);
|
|
267550
268016
|
const reversedPointLayerScopes = useMemo$1(() => [...pointLayerScopes || []].reverse(), [pointLayerScopes]);
|
|
267551
|
-
return jsxRuntimeExports.jsxs("div", { children: [anyLayerHasZ ? jsxRuntimeExports.jsx(GlobalDimensionSlider, { label: "Z", targetValue: targetZ, setTargetValue: setTargetZ, max: maxZ, spatialRenderingMode, setSpatialRenderingMode }) : null, anyLayerHasT ? jsxRuntimeExports.jsx(GlobalDimensionSlider, { label: "T", targetValue: targetT, setTargetValue: setTargetT, max: maxT }) : null, pointLayerScopes && reversedPointLayerScopes.map((layerScope) => jsxRuntimeExports.jsx(PointLayerController, { theme, layerScope, layerCoordination: pointLayerCoordination[0][layerScope], setLayerCoordination: pointLayerCoordination[1][layerScope] }, layerScope)), spotLayerScopes && reversedSpotLayerScopes.map((layerScope) => jsxRuntimeExports.jsx(SpotLayerController, { theme, layerScope, layerCoordination: spotLayerCoordination[0][layerScope], setLayerCoordination: spotLayerCoordination[1][layerScope] }, layerScope)), segmentationLayerScopes && reversedSegmentationLayerScopes.map((layerScope) => jsxRuntimeExports.jsx(SegmentationLayerController, { theme, layerScope, layerCoordination: segmentationLayerCoordination[0][layerScope], setLayerCoordination: segmentationLayerCoordination[1][layerScope], channelScopes: segmentationChannelScopesByLayer[layerScope], channelCoordination: segmentationChannelCoordination[0][layerScope], setChannelCoordination: segmentationChannelCoordination[1][layerScope] }, layerScope)), imageLayerScopes && reversedImageLayerScopes.map((layerScope) => jsxRuntimeExports.jsx(ImageLayerController, { theme, coordinationScopesRaw, layerScope, layerCoordination: imageLayerCoordination[0][layerScope], setLayerCoordination: imageLayerCoordination[1][layerScope], channelScopes: imageChannelScopesByLayer[layerScope], channelCoordination: imageChannelCoordination[0][layerScope], setChannelCoordination: imageChannelCoordination[1][layerScope], image: images[layerScope]?.image?.instance, featureIndex: images[layerScope]?.featureIndex, targetT, targetZ, spatialRenderingMode, volumeLoadingProgress: volumeLoadingStatus?.loadingProgress, onStopVolumeLoading: volumeLoadingStatus?.onStopLoading, onRestartVolumeLoading: volumeLoadingStatus?.onRestartLoading, volumeStillRef: volumeLoadingStatus?.stillRef }, layerScope))] });
|
|
268017
|
+
return jsxRuntimeExports.jsxs("div", { children: [anyLayerHasZ ? jsxRuntimeExports.jsx(GlobalDimensionSlider, { label: "Z", targetValue: targetZ, setTargetValue: setTargetZ, max: maxZ, spatialRenderingMode, setSpatialRenderingMode }) : null, anyLayerHasT ? jsxRuntimeExports.jsx(GlobalDimensionSlider, { label: "T", targetValue: targetT, setTargetValue: setTargetT, max: maxT }) : null, pointLayerScopes && reversedPointLayerScopes.map((layerScope) => jsxRuntimeExports.jsx(PointLayerController, { theme, layerScope, layerCoordination: pointLayerCoordination[0][layerScope], setLayerCoordination: pointLayerCoordination[1][layerScope], pointMatrixIndicesData: pointMultiIndicesData?.[layerScope], tiledPointsLoadingProgress }, layerScope)), spotLayerScopes && reversedSpotLayerScopes.map((layerScope) => jsxRuntimeExports.jsx(SpotLayerController, { theme, layerScope, layerCoordination: spotLayerCoordination[0][layerScope], setLayerCoordination: spotLayerCoordination[1][layerScope] }, layerScope)), segmentationLayerScopes && reversedSegmentationLayerScopes.map((layerScope) => jsxRuntimeExports.jsx(SegmentationLayerController, { theme, layerScope, layerCoordination: segmentationLayerCoordination[0][layerScope], setLayerCoordination: segmentationLayerCoordination[1][layerScope], channelScopes: segmentationChannelScopesByLayer[layerScope], channelCoordination: segmentationChannelCoordination[0][layerScope], setChannelCoordination: segmentationChannelCoordination[1][layerScope] }, layerScope)), imageLayerScopes && reversedImageLayerScopes.map((layerScope) => jsxRuntimeExports.jsx(ImageLayerController, { theme, coordinationScopesRaw, layerScope, layerCoordination: imageLayerCoordination[0][layerScope], setLayerCoordination: imageLayerCoordination[1][layerScope], channelScopes: imageChannelScopesByLayer[layerScope], channelCoordination: imageChannelCoordination[0][layerScope], setChannelCoordination: imageChannelCoordination[1][layerScope], image: images[layerScope]?.image?.instance, featureIndex: images[layerScope]?.featureIndex, targetT, targetZ, spatialRenderingMode, volumeLoadingProgress: volumeLoadingStatus?.loadingProgress, onStopVolumeLoading: volumeLoadingStatus?.onStopLoading, onRestartVolumeLoading: volumeLoadingStatus?.onRestartLoading, volumeStillRef: volumeLoadingStatus?.stillRef }, layerScope))] });
|
|
267552
268018
|
}
|
|
267553
268019
|
function LayerControllerSubscriber(props) {
|
|
267554
268020
|
const { coordinationScopes: coordinationScopesRaw, coordinationScopesBy: coordinationScopesByRaw, closeButtonVisible, downloadButtonVisible, removeGridComponent, theme, title: title2 = "Spatial Layers", uuid: uuid2 } = props;
|
|
@@ -267632,6 +268098,8 @@ function LayerControllerSubscriber(props) {
|
|
|
267632
268098
|
CoordinationType$1.SPATIAL_LAYER_OPACITY,
|
|
267633
268099
|
CoordinationType$1.SPATIAL_SPOT_RADIUS,
|
|
267634
268100
|
CoordinationType$1.OBS_COLOR_ENCODING,
|
|
268101
|
+
CoordinationType$1.FEATURE_COLOR,
|
|
268102
|
+
CoordinationType$1.FEATURE_FILTER_MODE,
|
|
267635
268103
|
CoordinationType$1.FEATURE_SELECTION,
|
|
267636
268104
|
CoordinationType$1.FEATURE_VALUE_COLORMAP,
|
|
267637
268105
|
CoordinationType$1.FEATURE_VALUE_COLORMAP_RANGE,
|
|
@@ -267640,7 +268108,10 @@ function LayerControllerSubscriber(props) {
|
|
|
267640
268108
|
CoordinationType$1.TOOLTIP_CROSSHAIRS_VISIBLE,
|
|
267641
268109
|
CoordinationType$1.LEGEND_VISIBLE
|
|
267642
268110
|
], coordinationScopes, coordinationScopesBy, CoordinationType$1.POINT_LAYER);
|
|
267643
|
-
const [{ volumeLoadingProgress: volumeLoadingStatus }] = useAuxiliaryCoordination([
|
|
268111
|
+
const [{ volumeLoadingProgress: volumeLoadingStatus, tiledPointsLoadingProgress }] = useAuxiliaryCoordination([
|
|
268112
|
+
"spatialAcceleratedVolumeLoadingProgress",
|
|
268113
|
+
"spatialTiledPointsLoadingProgress"
|
|
268114
|
+
], coordinationScopes);
|
|
267644
268115
|
const [spatialLayout] = useComponentLayout("spatial", ["spatialImageLayer"], coordinationScopes);
|
|
267645
268116
|
const layerControllerRef = useRef();
|
|
267646
268117
|
const [componentWidth, componentHeight] = useClosestVitessceContainerSize(layerControllerRef);
|
|
@@ -267649,19 +268120,22 @@ function LayerControllerSubscriber(props) {
|
|
|
267649
268120
|
const [imageData, imageDataStatus, imageUrls, imageErrors] = useMultiImages(coordinationScopes, coordinationScopesBy, loaders, dataset, mergeCoordination, uuid2);
|
|
267650
268121
|
const [obsSpotsData, obsSpotsDataStatus, obsSpotsUrls, obsSpotsErrors] = useMultiObsSpots(coordinationScopes, coordinationScopesBy, loaders, dataset, mergeCoordination, uuid2);
|
|
267651
268122
|
const [obsPointsData, obsPointsDataStatus, obsPointsUrls, obsPointsErrors] = useMultiObsPoints(coordinationScopes, coordinationScopesBy, loaders, dataset, mergeCoordination, uuid2);
|
|
268123
|
+
const [pointMultiIndicesData, pointMultiIndicesDataStatus, pointMultiIndicesDataErrors] = usePointMultiObsFeatureMatrixIndices(coordinationScopes, coordinationScopesBy, loaders, dataset);
|
|
267652
268124
|
const errors = [
|
|
267653
268125
|
...obsSegmentationsErrors,
|
|
267654
268126
|
...imageErrors,
|
|
267655
268127
|
...obsSpotsErrors,
|
|
267656
|
-
...obsPointsErrors
|
|
268128
|
+
...obsPointsErrors,
|
|
268129
|
+
...pointMultiIndicesDataErrors
|
|
267657
268130
|
];
|
|
267658
268131
|
const isReady = useReady([
|
|
267659
268132
|
obsSpotsDataStatus,
|
|
267660
268133
|
obsPointsDataStatus,
|
|
267661
268134
|
obsSegmentationsDataStatus,
|
|
267662
|
-
imageDataStatus
|
|
268135
|
+
imageDataStatus,
|
|
268136
|
+
pointMultiIndicesDataStatus
|
|
267663
268137
|
]);
|
|
267664
|
-
return jsxRuntimeExports.jsx(TitleInfo, { title: title2, isScroll: true, closeButtonVisible, downloadButtonVisible, removeGridComponent, theme, isReady, errors, children: jsxRuntimeExports.jsx(LayerController, { theme, coordinationScopesRaw, segmentationLayerScopes, segmentationLayerCoordination, segmentationChannelScopesByLayer, segmentationChannelCoordination, images: imageData, imageLayerScopes, imageLayerCoordination, targetT, targetZ, setTargetT, setTargetZ, spatialRenderingMode, setSpatialRenderingMode, imageChannelScopesByLayer, imageChannelCoordination, spotLayerScopes, spotLayerCoordination, pointLayerScopes, pointLayerCoordination, volumeLoadingStatus }) });
|
|
268138
|
+
return jsxRuntimeExports.jsx(TitleInfo, { title: title2, isScroll: true, closeButtonVisible, downloadButtonVisible, removeGridComponent, theme, isReady, errors, children: jsxRuntimeExports.jsx(LayerController, { theme, coordinationScopesRaw, segmentationLayerScopes, segmentationLayerCoordination, segmentationChannelScopesByLayer, segmentationChannelCoordination, images: imageData, imageLayerScopes, imageLayerCoordination, targetT, targetZ, setTargetT, setTargetZ, spatialRenderingMode, setSpatialRenderingMode, imageChannelScopesByLayer, imageChannelCoordination, spotLayerScopes, spotLayerCoordination, pointLayerScopes, pointLayerCoordination, pointMultiIndicesData, volumeLoadingStatus, tiledPointsLoadingProgress }) });
|
|
267665
268139
|
}
|
|
267666
268140
|
const isIterable$2 = (obj) => Symbol.iterator in obj;
|
|
267667
268141
|
const hasIterableEntries = (value2) => (
|
|
@@ -269576,7 +270050,7 @@ function HiglassGlobalStyles(props) {
|
|
|
269576
270050
|
}
|
|
269577
270051
|
register({ dataFetcher: ZarrMultivecDataFetcher_default, config: ZarrMultivecDataFetcher_default.config }, { pluginType: "dataFetcher" });
|
|
269578
270052
|
const LazyHiGlassComponent = React__default.lazy(async () => {
|
|
269579
|
-
const { HiGlassComponent } = await import("./higlass-
|
|
270053
|
+
const { HiGlassComponent } = await import("./higlass-Baa_gFVD.js");
|
|
269580
270054
|
return { default: HiGlassComponent };
|
|
269581
270055
|
});
|
|
269582
270056
|
const HG_SIZE = 800;
|
|
@@ -272523,7 +272997,7 @@ function NeuroglancerGlobalStyles(props) {
|
|
|
272523
272997
|
const { classes: classes2 } = props;
|
|
272524
272998
|
return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(GlobalStyles$3, { styles: globalNeuroglancerCss }), jsxRuntimeExports.jsx(ScopedGlobalStyles, { styles: globalNeuroglancerStyles, parentClassName: classes2.neuroglancerWrapper })] });
|
|
272525
272999
|
}
|
|
272526
|
-
const LazyReactNeuroglancer = React__default.lazy(() => import("./ReactNeuroglancer-
|
|
273000
|
+
const LazyReactNeuroglancer = React__default.lazy(() => import("./ReactNeuroglancer-BfXvm92G.js"));
|
|
272527
273001
|
function createWorker() {
|
|
272528
273002
|
return new WorkerFactory();
|
|
272529
273003
|
}
|
|
@@ -293697,7 +294171,7 @@ function cureLocalIntersections(start2, triangles, dim) {
|
|
|
293697
294171
|
let p = start2;
|
|
293698
294172
|
do {
|
|
293699
294173
|
const a2 = p.prev, b2 = p.next.next;
|
|
293700
|
-
if (!equals$1(a2, b2) && intersects$
|
|
294174
|
+
if (!equals$1(a2, b2) && intersects$3(a2, p, p.next, b2) && locallyInside(a2, b2) && locallyInside(b2, a2)) {
|
|
293701
294175
|
triangles.push(a2.i / dim | 0);
|
|
293702
294176
|
triangles.push(p.i / dim | 0);
|
|
293703
294177
|
triangles.push(b2.i / dim | 0);
|
|
@@ -293875,7 +294349,7 @@ function area$3(p, q, r3) {
|
|
|
293875
294349
|
function equals$1(p1, p2) {
|
|
293876
294350
|
return p1.x === p2.x && p1.y === p2.y;
|
|
293877
294351
|
}
|
|
293878
|
-
function intersects$
|
|
294352
|
+
function intersects$3(p1, q1, p2, q2) {
|
|
293879
294353
|
const o1 = sign$2(area$3(p1, q1, p2));
|
|
293880
294354
|
const o2 = sign$2(area$3(p1, q1, q2));
|
|
293881
294355
|
const o3 = sign$2(area$3(p2, q2, p1));
|
|
@@ -293896,7 +294370,7 @@ function sign$2(num) {
|
|
|
293896
294370
|
function intersectsPolygon(a2, b2) {
|
|
293897
294371
|
let p = a2;
|
|
293898
294372
|
do {
|
|
293899
|
-
if (p.i !== a2.i && p.next.i !== a2.i && p.i !== b2.i && p.next.i !== b2.i && intersects$
|
|
294373
|
+
if (p.i !== a2.i && p.next.i !== a2.i && p.i !== b2.i && p.next.i !== b2.i && intersects$3(p, p.next, a2, b2)) return true;
|
|
293900
294374
|
p = p.next;
|
|
293901
294375
|
} while (p !== a2);
|
|
293902
294376
|
return false;
|
|
@@ -322907,7 +323381,7 @@ function place(b2, a2, c2) {
|
|
|
322907
323381
|
c2.y = a2.y;
|
|
322908
323382
|
}
|
|
322909
323383
|
}
|
|
322910
|
-
function intersects$
|
|
323384
|
+
function intersects$2(a2, b2) {
|
|
322911
323385
|
var dr = a2.r + b2.r - 1e-6, dx = b2.x - a2.x, dy = b2.y - a2.y;
|
|
322912
323386
|
return dr > 0 && dr * dr > dx * dx + dy * dy;
|
|
322913
323387
|
}
|
|
@@ -322937,13 +323411,13 @@ function packSiblingsRandom(circles, random2) {
|
|
|
322937
323411
|
j = b2.next, k = a2.previous, sj = b2._.r, sk = a2._.r;
|
|
322938
323412
|
do {
|
|
322939
323413
|
if (sj <= sk) {
|
|
322940
|
-
if (intersects$
|
|
323414
|
+
if (intersects$2(j._, c2._)) {
|
|
322941
323415
|
b2 = j, a2.next = b2, b2.previous = a2, --i2;
|
|
322942
323416
|
continue pack;
|
|
322943
323417
|
}
|
|
322944
323418
|
sj += j._.r, j = j.next;
|
|
322945
323419
|
} else {
|
|
322946
|
-
if (intersects$
|
|
323420
|
+
if (intersects$2(k._, c2._)) {
|
|
322947
323421
|
a2 = k, a2.next = b2, b2.previous = a2, --i2;
|
|
322948
323422
|
continue pack;
|
|
322949
323423
|
}
|
|
@@ -358529,7 +359003,7 @@ class ObsPointsCsvLoader extends CsvLoader {
|
|
|
358529
359003
|
data: [obsLocationsX, obsLocationsY],
|
|
358530
359004
|
shape: [2, obsLocationsX.length]
|
|
358531
359005
|
};
|
|
358532
|
-
this.cachedResult = { obsIndex, obsPoints };
|
|
359006
|
+
this.cachedResult = { obsIndex, obsPoints, obsPointsTilingType: "full" };
|
|
358533
359007
|
return this.cachedResult;
|
|
358534
359008
|
}
|
|
358535
359009
|
async load() {
|
|
@@ -360161,7 +360635,7 @@ class ObsPointsAnndataLoader extends AbstractTwoStepLoader {
|
|
|
360161
360635
|
this.dataSource.loadObsIndex(path2),
|
|
360162
360636
|
this.loadPoints()
|
|
360163
360637
|
]);
|
|
360164
|
-
return new LoaderResult({ obsIndex, obsPoints }, null, coordinationValues);
|
|
360638
|
+
return new LoaderResult({ obsIndex, obsPoints, obsPointsTilingType: "full" }, null, coordinationValues);
|
|
360165
360639
|
}
|
|
360166
360640
|
}
|
|
360167
360641
|
class ObsLocationsAnndataLoader extends AbstractTwoStepLoader {
|
|
@@ -361778,6 +362252,17 @@ class SpatialDataObsPointsLoader extends AbstractTwoStepLoader {
|
|
|
361778
362252
|
this.locations = locations;
|
|
361779
362253
|
return this.locations;
|
|
361780
362254
|
}
|
|
362255
|
+
async loadPointsInRect(bounds2, signal) {
|
|
362256
|
+
const { path: path2 } = this.options;
|
|
362257
|
+
let locations;
|
|
362258
|
+
const formatVersion = await this.dataSource.getPointsFormatVersion(path2);
|
|
362259
|
+
if (formatVersion === "0.1") {
|
|
362260
|
+
locations = await this.dataSource.loadPointsInRect(path2, bounds2, signal);
|
|
362261
|
+
} else {
|
|
362262
|
+
throw new UnknownSpatialDataFormatError("Only points format version 0.1 is supported.");
|
|
362263
|
+
}
|
|
362264
|
+
return locations;
|
|
362265
|
+
}
|
|
361781
362266
|
async loadObsIndex() {
|
|
361782
362267
|
const { tablePath, path: path2 } = this.options;
|
|
361783
362268
|
if (tablePath) {
|
|
@@ -361790,11 +362275,26 @@ class SpatialDataObsPointsLoader extends AbstractTwoStepLoader {
|
|
|
361790
362275
|
}
|
|
361791
362276
|
return null;
|
|
361792
362277
|
}
|
|
362278
|
+
async supportsTiling() {
|
|
362279
|
+
const { path: path2 } = this.options;
|
|
362280
|
+
const [formatVersion, zattrs, hasRequiredColumnsAndRowGroupSize] = await Promise.all([
|
|
362281
|
+
// Check the points format version.
|
|
362282
|
+
this.dataSource.getPointsFormatVersion(path2),
|
|
362283
|
+
// Check for the presence of bounding_box metadata.
|
|
362284
|
+
this.dataSource.loadSpatialDataElementAttrs(path2),
|
|
362285
|
+
// Check the size of parquet row groups,
|
|
362286
|
+
// and for the presence of morton_code_2d and feature_index columns.
|
|
362287
|
+
this.dataSource.supportsLoadPointsInRect(path2)
|
|
362288
|
+
]);
|
|
362289
|
+
const isSupportedVersion = formatVersion === "0.1";
|
|
362290
|
+
const boundingBox = zattrs?.bounding_box;
|
|
362291
|
+
const hasBoundingBox2D = typeof boundingBox?.x_max === "number" && typeof boundingBox?.x_min === "number" && typeof boundingBox?.y_max === "number" && typeof boundingBox?.y_min === "number";
|
|
362292
|
+
return isSupportedVersion && hasBoundingBox2D && hasRequiredColumnsAndRowGroupSize;
|
|
362293
|
+
}
|
|
361793
362294
|
async load() {
|
|
361794
|
-
const [
|
|
361795
|
-
this.
|
|
361796
|
-
this.
|
|
361797
|
-
this.loadModelMatrix()
|
|
362295
|
+
const [modelMatrix2, supportsTiling] = await Promise.all([
|
|
362296
|
+
this.loadModelMatrix(),
|
|
362297
|
+
this.supportsTiling()
|
|
361798
362298
|
]);
|
|
361799
362299
|
const coordinationValues = {
|
|
361800
362300
|
pointLayer: CL({
|
|
@@ -361810,7 +362310,36 @@ class SpatialDataObsPointsLoader extends AbstractTwoStepLoader {
|
|
|
361810
362310
|
// additionalObsSets: null,
|
|
361811
362311
|
})
|
|
361812
362312
|
};
|
|
361813
|
-
|
|
362313
|
+
let obsIndex = null;
|
|
362314
|
+
let obsPoints = null;
|
|
362315
|
+
const featureIndices = null;
|
|
362316
|
+
if (!supportsTiling) {
|
|
362317
|
+
[obsIndex, obsPoints] = await Promise.all([
|
|
362318
|
+
this.loadObsIndex(),
|
|
362319
|
+
this.loadPoints()
|
|
362320
|
+
]);
|
|
362321
|
+
}
|
|
362322
|
+
return new LoaderResult({
|
|
362323
|
+
/* obsIndex: ["1"], // TEMP
|
|
362324
|
+
obsPoints: { // TEMP
|
|
362325
|
+
shape: [2, 1],
|
|
362326
|
+
data: [[0], [0]],
|
|
362327
|
+
}, */
|
|
362328
|
+
// These will be null if tiling is supported.
|
|
362329
|
+
obsIndex,
|
|
362330
|
+
obsPoints,
|
|
362331
|
+
featureIndices,
|
|
362332
|
+
obsPointsModelMatrix: modelMatrix2,
|
|
362333
|
+
// Return 'tiled' if the morton_code_2d column
|
|
362334
|
+
// and bounding_box metadata are present,
|
|
362335
|
+
// and the row group size is small enough.
|
|
362336
|
+
// Otherwise, return 'full'.
|
|
362337
|
+
obsPointsTilingType: supportsTiling ? "tiled" : "full",
|
|
362338
|
+
// TEMPORARY: probably makes more sense to pass the loader instance all the way down.
|
|
362339
|
+
// Caller can then decide whether to use loader.load vs. loader.loadPointsInRect.
|
|
362340
|
+
// May need another function such as loader.supportsPointInRect() true/false.
|
|
362341
|
+
loadPointsInRect: this.loadPointsInRect.bind(this)
|
|
362342
|
+
}, null, coordinationValues);
|
|
361814
362343
|
}
|
|
361815
362344
|
}
|
|
361816
362345
|
class SpatialDataObsSetsLoader extends ObsSetsAnndataLoader {
|
|
@@ -371205,13 +371734,470 @@ function tableFromIPC(input) {
|
|
|
371205
371734
|
}
|
|
371206
371735
|
return new Table(reader.readAll());
|
|
371207
371736
|
}
|
|
371737
|
+
const MORTON_CODE_NUM_BITS = 32;
|
|
371738
|
+
const MORTON_CODE_VALUE_MAX = 2 ** (MORTON_CODE_NUM_BITS / 2) - 1;
|
|
371739
|
+
function origCoordToNormCoord(origCoord, origXMin, origXMax, origYMin, origYMax) {
|
|
371740
|
+
const [origX, origY] = origCoord;
|
|
371741
|
+
const origXRange = origXMax - origXMin;
|
|
371742
|
+
const origYRange = origYMax - origYMin;
|
|
371743
|
+
return [
|
|
371744
|
+
// Clamp to zero at low end, since using unsigned ints.
|
|
371745
|
+
Math.max(Math.floor((origX - origXMin) / origXRange * MORTON_CODE_VALUE_MAX), 0),
|
|
371746
|
+
Math.max(Math.floor((origY - origYMin) / origYRange * MORTON_CODE_VALUE_MAX), 0)
|
|
371747
|
+
];
|
|
371748
|
+
}
|
|
371749
|
+
function intersects$1(ax0, ay0, ax1, ay1, bx0, by0, bx1, by1) {
|
|
371750
|
+
return !(ax1 < bx0 || bx1 < ax0 || ay1 < by0 || by1 < ay0);
|
|
371751
|
+
}
|
|
371752
|
+
function contained(ix0, iy0, ix1, iy1, ox0, oy0, ox1, oy1) {
|
|
371753
|
+
return ox0 <= ix0 && ix0 <= ix1 && ix1 <= ox1 && (oy0 <= iy0 && iy0 <= iy1 && iy1 <= oy1);
|
|
371754
|
+
}
|
|
371755
|
+
function pointInside(x2, y2, rx0, ry0, rx1, ry1) {
|
|
371756
|
+
return rx0 <= x2 && x2 <= rx1 && (ry0 <= y2 && y2 <= ry1);
|
|
371757
|
+
}
|
|
371758
|
+
function cellRange(prefix2, level, bits) {
|
|
371759
|
+
const shift2 = 2 * (bits - level);
|
|
371760
|
+
const power = 2 ** shift2;
|
|
371761
|
+
const lo = prefix2 * power;
|
|
371762
|
+
const hi = (prefix2 + 1) * power - 1;
|
|
371763
|
+
return [lo, hi];
|
|
371764
|
+
}
|
|
371765
|
+
function mergeAdjacent(intervals2) {
|
|
371766
|
+
if (intervals2.length === 0) {
|
|
371767
|
+
return [];
|
|
371768
|
+
}
|
|
371769
|
+
intervals2.sort((a2, b2) => a2[0] - b2[0]);
|
|
371770
|
+
const merged = [intervals2[0]];
|
|
371771
|
+
for (let i2 = 1; i2 < intervals2.length; i2++) {
|
|
371772
|
+
const [lo, hi] = intervals2[i2];
|
|
371773
|
+
const [mlo, mhi] = merged[merged.length - 1];
|
|
371774
|
+
if (lo <= mhi + 1) {
|
|
371775
|
+
merged[merged.length - 1] = [mlo, Math.max(mhi, hi)];
|
|
371776
|
+
} else {
|
|
371777
|
+
merged.push([lo, hi]);
|
|
371778
|
+
}
|
|
371779
|
+
}
|
|
371780
|
+
return merged;
|
|
371781
|
+
}
|
|
371782
|
+
function zcoverRectangle(rx0, ry0, rx1, ry1, bits, stopLevel = null, merge2 = true) {
|
|
371783
|
+
const maxCoord = (1 << bits) - 1;
|
|
371784
|
+
if (!(rx0 >= 0 && rx0 <= rx1 && rx1 <= maxCoord && ry0 >= 0 && ry0 <= ry1 && ry1 <= maxCoord)) {
|
|
371785
|
+
throw new Error("Rectangle out of bounds for given bits.");
|
|
371786
|
+
}
|
|
371787
|
+
const intervals2 = [];
|
|
371788
|
+
const stack2 = [[0, 0, 0, 0, maxCoord, maxCoord]];
|
|
371789
|
+
while (stack2.length > 0) {
|
|
371790
|
+
const [prefix2, level, xmin, ymin, xmax, ymax] = stack2.pop();
|
|
371791
|
+
if (!intersects$1(xmin, ymin, xmax, ymax, rx0, ry0, rx1, ry1)) {
|
|
371792
|
+
continue;
|
|
371793
|
+
}
|
|
371794
|
+
if (stopLevel !== null && level === stopLevel) {
|
|
371795
|
+
intervals2.push(cellRange(prefix2, level, bits));
|
|
371796
|
+
continue;
|
|
371797
|
+
}
|
|
371798
|
+
if (contained(xmin, ymin, xmax, ymax, rx0, ry0, rx1, ry1)) {
|
|
371799
|
+
intervals2.push(cellRange(prefix2, level, bits));
|
|
371800
|
+
continue;
|
|
371801
|
+
}
|
|
371802
|
+
if (level === bits) {
|
|
371803
|
+
if (pointInside(xmin, ymin, rx0, ry0, rx1, ry1)) {
|
|
371804
|
+
intervals2.push(cellRange(prefix2, level, bits));
|
|
371805
|
+
}
|
|
371806
|
+
continue;
|
|
371807
|
+
}
|
|
371808
|
+
const midx = Math.floor((xmin + xmax) / 2);
|
|
371809
|
+
const midy = Math.floor((ymin + ymax) / 2);
|
|
371810
|
+
stack2.push([prefix2 << 2 | 0, level + 1, xmin, ymin, midx, midy]);
|
|
371811
|
+
stack2.push([prefix2 << 2 | 1, level + 1, midx + 1, ymin, xmax, midy]);
|
|
371812
|
+
stack2.push([prefix2 << 2 | 2, level + 1, xmin, midy + 1, midx, ymax]);
|
|
371813
|
+
stack2.push([prefix2 << 2 | 3, level + 1, midx + 1, midy + 1, xmax, ymax]);
|
|
371814
|
+
}
|
|
371815
|
+
return merge2 ? mergeAdjacent(intervals2) : intervals2;
|
|
371816
|
+
}
|
|
371817
|
+
function sdataMortonQueryRectAux(boundingBox, origRect) {
|
|
371818
|
+
const xMin = boundingBox.x_min;
|
|
371819
|
+
const xMax = boundingBox.x_max;
|
|
371820
|
+
const yMin = boundingBox.y_min;
|
|
371821
|
+
const yMax = boundingBox.y_max;
|
|
371822
|
+
const normRect = [
|
|
371823
|
+
origCoordToNormCoord(origRect[0], xMin, xMax, yMin, yMax),
|
|
371824
|
+
origCoordToNormCoord(origRect[1], xMin, xMax, yMin, yMax)
|
|
371825
|
+
];
|
|
371826
|
+
const mortonIntervals = zcoverRectangle(normRect[0][0], normRect[0][1], normRect[1][0], normRect[1][1], 16, null, true);
|
|
371827
|
+
return mortonIntervals;
|
|
371828
|
+
}
|
|
371208
371829
|
async function getParquetModule() {
|
|
371209
371830
|
const module2 = await import(
|
|
371210
371831
|
/* webpackIgnore: true */
|
|
371211
|
-
"https://
|
|
371832
|
+
"https://cdn.vitessce.io/parquet-wasm@2c23652/esm/parquet_wasm.js"
|
|
371212
371833
|
);
|
|
371213
371834
|
await module2.default();
|
|
371214
|
-
return {
|
|
371835
|
+
return {
|
|
371836
|
+
readParquet: module2.readParquet,
|
|
371837
|
+
readSchema: module2.readSchema,
|
|
371838
|
+
readMetadata: module2.readMetadata,
|
|
371839
|
+
// Added in fork
|
|
371840
|
+
readParquetRowGroup: module2.readParquetRowGroup
|
|
371841
|
+
// Added in fork
|
|
371842
|
+
};
|
|
371843
|
+
}
|
|
371844
|
+
async function _getParquetModule({ queryClient }) {
|
|
371845
|
+
return queryClient.fetchQuery({
|
|
371846
|
+
queryKey: ["parquetModule"],
|
|
371847
|
+
staleTime: Infinity,
|
|
371848
|
+
queryFn: getParquetModule,
|
|
371849
|
+
meta: { queryClient }
|
|
371850
|
+
});
|
|
371851
|
+
}
|
|
371852
|
+
async function _loadParquetBytes({ queryClient, store }, parquetPath, rangeQuery = void 0, partIndex = void 0) {
|
|
371853
|
+
return queryClient.fetchQuery({
|
|
371854
|
+
queryKey: ["SpatialDataTableSource", "_loadParquetBytes", parquetPath, rangeQuery, partIndex],
|
|
371855
|
+
staleTime: Infinity,
|
|
371856
|
+
queryFn: async (ctx) => {
|
|
371857
|
+
const store2 = ctx.meta?.store;
|
|
371858
|
+
const rangeQuery2 = ctx.queryKey[3];
|
|
371859
|
+
const { offset: offset2, length: length2, suffixLength } = rangeQuery2 || {};
|
|
371860
|
+
let getter2 = (path2) => store2.get(path2);
|
|
371861
|
+
if (rangeQuery2 !== void 0 && store2.getRange) {
|
|
371862
|
+
if (suffixLength !== void 0) {
|
|
371863
|
+
getter2 = (path2) => store2.getRange(path2, {
|
|
371864
|
+
suffixLength
|
|
371865
|
+
});
|
|
371866
|
+
} else {
|
|
371867
|
+
getter2 = (path2) => store2.getRange(path2, {
|
|
371868
|
+
offset: offset2,
|
|
371869
|
+
length: length2
|
|
371870
|
+
});
|
|
371871
|
+
}
|
|
371872
|
+
}
|
|
371873
|
+
let parquetBytes;
|
|
371874
|
+
if (partIndex === void 0) {
|
|
371875
|
+
parquetBytes = await getter2(`/${parquetPath}`);
|
|
371876
|
+
}
|
|
371877
|
+
if (!parquetBytes) {
|
|
371878
|
+
const part0Path = `${parquetPath}/part.${partIndex ?? 0}.parquet`;
|
|
371879
|
+
parquetBytes = await getter2(`/${part0Path}`);
|
|
371880
|
+
}
|
|
371881
|
+
return parquetBytes;
|
|
371882
|
+
},
|
|
371883
|
+
meta: { store }
|
|
371884
|
+
});
|
|
371885
|
+
}
|
|
371886
|
+
async function _loadParquetSchemaBytes({ queryClient, store }, parquetPath, partIndex = void 0) {
|
|
371887
|
+
return queryClient.fetchQuery({
|
|
371888
|
+
queryKey: ["SpatialDataTableSource", "_loadParquetSchemaBytes", parquetPath, partIndex],
|
|
371889
|
+
staleTime: Infinity,
|
|
371890
|
+
queryFn: async (ctx) => {
|
|
371891
|
+
const store2 = ctx.meta?.store;
|
|
371892
|
+
if (store2.getRange) {
|
|
371893
|
+
const TAIL_LENGTH = 8;
|
|
371894
|
+
let partZeroPath = parquetPath;
|
|
371895
|
+
let tailBytes = await store2.getRange(`/${partZeroPath}`, {
|
|
371896
|
+
suffixLength: TAIL_LENGTH
|
|
371897
|
+
});
|
|
371898
|
+
if (!tailBytes) {
|
|
371899
|
+
partZeroPath = `${parquetPath}/part.${partIndex ?? 0}.parquet`;
|
|
371900
|
+
tailBytes = await store2.getRange(`/${partZeroPath}`, {
|
|
371901
|
+
suffixLength: TAIL_LENGTH
|
|
371902
|
+
});
|
|
371903
|
+
}
|
|
371904
|
+
if (!tailBytes || tailBytes.length < TAIL_LENGTH) {
|
|
371905
|
+
throw new Error(`Failed to load parquet footerLength for ${partZeroPath}`);
|
|
371906
|
+
}
|
|
371907
|
+
const footerLength = new DataView(tailBytes.buffer).getInt32(0, true);
|
|
371908
|
+
const magic = new TextDecoder().decode(tailBytes.slice(4, 8));
|
|
371909
|
+
if (magic !== "PAR1") {
|
|
371910
|
+
throw new Error("Invalid Parquet file: missing PAR1 magic number");
|
|
371911
|
+
}
|
|
371912
|
+
const footerBytes = await store2.getRange(`/${partZeroPath}`, {
|
|
371913
|
+
suffixLength: footerLength + TAIL_LENGTH
|
|
371914
|
+
});
|
|
371915
|
+
if (!footerBytes || footerBytes.length !== footerLength + TAIL_LENGTH) {
|
|
371916
|
+
throw new Error(`Failed to load parquet footer bytes for ${parquetPath}`);
|
|
371917
|
+
}
|
|
371918
|
+
return footerBytes;
|
|
371919
|
+
}
|
|
371920
|
+
return null;
|
|
371921
|
+
},
|
|
371922
|
+
meta: { queryClient, store }
|
|
371923
|
+
});
|
|
371924
|
+
}
|
|
371925
|
+
async function _loadParquetMetadataByPart({ queryClient, store }, parquetPath) {
|
|
371926
|
+
return queryClient.fetchQuery({
|
|
371927
|
+
queryKey: ["SpatialDataTableSource", "_loadParquetMetadataByPart", parquetPath],
|
|
371928
|
+
staleTime: Infinity,
|
|
371929
|
+
queryFn: async (ctx) => {
|
|
371930
|
+
const queryClient2 = (
|
|
371931
|
+
/** @type {QueryClient} */
|
|
371932
|
+
ctx.meta?.queryClient
|
|
371933
|
+
);
|
|
371934
|
+
const { readSchema, readMetadata } = await _getParquetModule({ queryClient: queryClient2 });
|
|
371935
|
+
let partIndex = 0;
|
|
371936
|
+
let numParts;
|
|
371937
|
+
const allMetadata = [];
|
|
371938
|
+
do {
|
|
371939
|
+
try {
|
|
371940
|
+
const schemaBytes = await _loadParquetSchemaBytes({ queryClient: queryClient2, store }, parquetPath, partIndex);
|
|
371941
|
+
if (schemaBytes) {
|
|
371942
|
+
const wasmSchema = readSchema(schemaBytes);
|
|
371943
|
+
const arrowTableForSchema = tableFromIPC(wasmSchema.intoIPCStream());
|
|
371944
|
+
const partMetadata = readMetadata(schemaBytes);
|
|
371945
|
+
const partInfo = {
|
|
371946
|
+
schema: arrowTableForSchema,
|
|
371947
|
+
schemaBytes,
|
|
371948
|
+
metadata: partMetadata
|
|
371949
|
+
};
|
|
371950
|
+
allMetadata.push(partInfo);
|
|
371951
|
+
partIndex += 1;
|
|
371952
|
+
}
|
|
371953
|
+
} catch (error2) {
|
|
371954
|
+
if (error2.message.includes("Failed to load parquet footerLength")) {
|
|
371955
|
+
numParts = partIndex;
|
|
371956
|
+
}
|
|
371957
|
+
}
|
|
371958
|
+
} while (numParts === void 0);
|
|
371959
|
+
const metadata2 = {
|
|
371960
|
+
numRows: 0,
|
|
371961
|
+
numRowGroups: 0,
|
|
371962
|
+
numRowsPerGroup: 0,
|
|
371963
|
+
schema: null
|
|
371964
|
+
};
|
|
371965
|
+
if (allMetadata.length > 0) {
|
|
371966
|
+
const firstPart = allMetadata[0];
|
|
371967
|
+
metadata2.numRows = allMetadata.reduce((sum2, part) => sum2 + part.metadata.fileMetadata().numRows(), 0);
|
|
371968
|
+
metadata2.numRowGroups = allMetadata.reduce((sum2, part) => sum2 + part.metadata.numRowGroups(), 0);
|
|
371969
|
+
metadata2.numRowsPerGroup = firstPart.metadata.rowGroup(0).numRows();
|
|
371970
|
+
metadata2.schema = firstPart.schema.schema;
|
|
371971
|
+
}
|
|
371972
|
+
const result = {
|
|
371973
|
+
...metadata2,
|
|
371974
|
+
// TODO: extract metadata per part and rowGroup into plain objects that match the hyparquet parquetMetadata() return value?
|
|
371975
|
+
// This will also make it easier to test.
|
|
371976
|
+
parts: allMetadata
|
|
371977
|
+
};
|
|
371978
|
+
return result;
|
|
371979
|
+
},
|
|
371980
|
+
meta: { queryClient }
|
|
371981
|
+
});
|
|
371982
|
+
}
|
|
371983
|
+
async function _loadParquetRowGroupByGroupIndex({ queryClient, store }, parquetPath, rowGroupIndex) {
|
|
371984
|
+
return queryClient.fetchQuery({
|
|
371985
|
+
queryKey: ["SpatialDataTableSource", "_loadParquetRowGroupByGroupIndex", parquetPath, rowGroupIndex],
|
|
371986
|
+
staleTime: Infinity,
|
|
371987
|
+
queryFn: async (ctx) => {
|
|
371988
|
+
const queryClient2 = (
|
|
371989
|
+
/** @type {QueryClient} */
|
|
371990
|
+
ctx.meta?.queryClient
|
|
371991
|
+
);
|
|
371992
|
+
const store2 = ctx.meta?.store;
|
|
371993
|
+
const { readParquetRowGroup } = await _getParquetModule({ queryClient: queryClient2 });
|
|
371994
|
+
const allMetadata = await _loadParquetMetadataByPart({ queryClient: queryClient2, store: store2 }, parquetPath);
|
|
371995
|
+
if (rowGroupIndex < 0 || rowGroupIndex >= allMetadata.numRowGroups) {
|
|
371996
|
+
throw new Error(`Row group index ${rowGroupIndex} is out of bounds for parquet table with ${allMetadata.numRowGroups} row groups.`);
|
|
371997
|
+
}
|
|
371998
|
+
let partIndex;
|
|
371999
|
+
let cumulativeRowGroups = 0;
|
|
372000
|
+
for (let i2 = 0; i2 < allMetadata.parts.length; i2++) {
|
|
372001
|
+
const part = allMetadata.parts[i2];
|
|
372002
|
+
const numRowGroupsInPart = part.metadata.numRowGroups();
|
|
372003
|
+
if (rowGroupIndex < cumulativeRowGroups + numRowGroupsInPart) {
|
|
372004
|
+
partIndex = i2;
|
|
372005
|
+
break;
|
|
372006
|
+
}
|
|
372007
|
+
cumulativeRowGroups += numRowGroupsInPart;
|
|
372008
|
+
}
|
|
372009
|
+
if (partIndex === void 0) {
|
|
372010
|
+
throw new Error(`Failed to find part containing row group index ${rowGroupIndex}.`);
|
|
372011
|
+
}
|
|
372012
|
+
const partMetadata = allMetadata.parts[partIndex].metadata;
|
|
372013
|
+
const { schemaBytes } = allMetadata.parts[partIndex];
|
|
372014
|
+
const rowGroupIndexRelativeToPart = rowGroupIndex - cumulativeRowGroups;
|
|
372015
|
+
const rowGroupMetadata = partMetadata.rowGroup(rowGroupIndexRelativeToPart);
|
|
372016
|
+
const rowGroupFileOffset = rowGroupMetadata.fileOffset();
|
|
372017
|
+
const rowGroupCompressedSize = rowGroupMetadata.compressedSize();
|
|
372018
|
+
const rowGroupBytes = await _loadParquetBytes({ queryClient: queryClient2, store: store2 }, parquetPath, { offset: rowGroupFileOffset, length: rowGroupCompressedSize }, partIndex);
|
|
372019
|
+
const rowGroupIPC = readParquetRowGroup(schemaBytes, rowGroupBytes, rowGroupIndexRelativeToPart).intoIPCStream();
|
|
372020
|
+
const rowGroupTable = tableFromIPC(rowGroupIPC);
|
|
372021
|
+
return rowGroupTable;
|
|
372022
|
+
},
|
|
372023
|
+
meta: { queryClient, store }
|
|
372024
|
+
});
|
|
372025
|
+
}
|
|
372026
|
+
async function _loadParquetRowGroupColumnExtent({ queryClient, store }, parquetPath, columnName, rowGroupIndex) {
|
|
372027
|
+
return queryClient.fetchQuery({
|
|
372028
|
+
queryKey: ["SpatialDataTableSource", "_loadParquetRowGroupColumnExtent", parquetPath, columnName, rowGroupIndex],
|
|
372029
|
+
staleTime: Infinity,
|
|
372030
|
+
queryFn: async (ctx) => {
|
|
372031
|
+
const queryClient2 = (
|
|
372032
|
+
/** @type {QueryClient} */
|
|
372033
|
+
ctx.meta?.queryClient
|
|
372034
|
+
);
|
|
372035
|
+
const store2 = ctx.meta?.store;
|
|
372036
|
+
const rowGroupTable = await _loadParquetRowGroupByGroupIndex({ queryClient: queryClient2, store: store2 }, parquetPath, rowGroupIndex);
|
|
372037
|
+
const column2 = rowGroupTable.getChild(columnName);
|
|
372038
|
+
if (!column2) {
|
|
372039
|
+
throw new Error(`Column ${columnName} not found in row group ${rowGroupIndex} of parquet table at ${parquetPath}.`);
|
|
372040
|
+
}
|
|
372041
|
+
if (column2.length === 0) {
|
|
372042
|
+
return { min: null, max: null };
|
|
372043
|
+
}
|
|
372044
|
+
return { min: column2.get(0), max: column2.get(column2.length - 1) };
|
|
372045
|
+
},
|
|
372046
|
+
meta: { queryClient, store }
|
|
372047
|
+
});
|
|
372048
|
+
}
|
|
372049
|
+
function getCachedInRangeSync(queryClient, parquetPath, columnName, lo, hi) {
|
|
372050
|
+
const queryCache = queryClient.getQueryCache();
|
|
372051
|
+
const prevQueries = queryCache.findAll({
|
|
372052
|
+
// Note: Must (manually) keep in sync with queryKey used in _loadParquetRowGroupColumnExtent.
|
|
372053
|
+
queryKey: ["SpatialDataTableSource", "_loadParquetRowGroupColumnExtent", parquetPath, columnName],
|
|
372054
|
+
exact: false
|
|
372055
|
+
});
|
|
372056
|
+
const cachedRowGroupInfo = prevQueries.map((q) => {
|
|
372057
|
+
if (!(q.state.status === "success" && !q.state.isInvalidated)) {
|
|
372058
|
+
return null;
|
|
372059
|
+
}
|
|
372060
|
+
return {
|
|
372061
|
+
queryKey: q.queryKey,
|
|
372062
|
+
index: q.queryKey[4],
|
|
372063
|
+
status: q.state.status,
|
|
372064
|
+
min: q.state.data?.min,
|
|
372065
|
+
max: q.state.data?.max
|
|
372066
|
+
};
|
|
372067
|
+
}).filter((v) => v !== null).toSorted((a2, b2) => a2.index - b2.index);
|
|
372068
|
+
return cachedRowGroupInfo.filter((c2) => c2.index >= lo && c2.index < hi);
|
|
372069
|
+
}
|
|
372070
|
+
async function getCachedInRange(queryClient, parquetPath, columnName, lo, hi) {
|
|
372071
|
+
const queryCache = queryClient.getQueryCache();
|
|
372072
|
+
const prevQueries = queryCache.findAll({
|
|
372073
|
+
// Note: Must (manually) keep in sync with queryKey used in _loadParquetRowGroupColumnExtent.
|
|
372074
|
+
queryKey: ["SpatialDataTableSource", "_loadParquetRowGroupColumnExtent", parquetPath, columnName],
|
|
372075
|
+
exact: false
|
|
372076
|
+
});
|
|
372077
|
+
const cachedRowGroupInfo = prevQueries.map((q) => ({
|
|
372078
|
+
queryKey: q.queryKey,
|
|
372079
|
+
index: q.queryKey[4],
|
|
372080
|
+
status: q.state.status,
|
|
372081
|
+
min: q.state.data?.min,
|
|
372082
|
+
max: q.state.data?.max
|
|
372083
|
+
})).filter((v) => v !== null).toSorted((a2, b2) => a2.index - b2.index);
|
|
372084
|
+
const cachedInRange = cachedRowGroupInfo.filter((c2) => c2.index >= lo && c2.index < hi);
|
|
372085
|
+
const pendingQueries = cachedInRange.filter((c2) => c2.status !== "success");
|
|
372086
|
+
if (pendingQueries.length === 0) {
|
|
372087
|
+
return cachedInRange;
|
|
372088
|
+
}
|
|
372089
|
+
const pendingPromises = pendingQueries.map((c2) => queryClient.ensureQueryData({
|
|
372090
|
+
queryKey: c2.queryKey
|
|
372091
|
+
}));
|
|
372092
|
+
await Promise.all(pendingPromises);
|
|
372093
|
+
return getCachedInRangeSync(queryClient, parquetPath, columnName, lo, hi);
|
|
372094
|
+
}
|
|
372095
|
+
async function _bisectRowGroupsRight({ queryClient, store }, parquetPath, columnName, targetValue) {
|
|
372096
|
+
return queryClient.fetchQuery({
|
|
372097
|
+
queryKey: ["SpatialDataTableSource", "_bisectRowGroupsRight", parquetPath, columnName, targetValue],
|
|
372098
|
+
staleTime: Infinity,
|
|
372099
|
+
queryFn: async (ctx) => {
|
|
372100
|
+
const queryClient2 = (
|
|
372101
|
+
/** @type {QueryClient} */
|
|
372102
|
+
ctx.meta?.queryClient
|
|
372103
|
+
);
|
|
372104
|
+
const store2 = ctx.meta?.store;
|
|
372105
|
+
const allMetadata = await _loadParquetMetadataByPart({ queryClient: queryClient2, store: store2 }, parquetPath);
|
|
372106
|
+
const { numRowGroups } = allMetadata;
|
|
372107
|
+
let lo = 0;
|
|
372108
|
+
let hi = numRowGroups;
|
|
372109
|
+
while (lo < hi) {
|
|
372110
|
+
const cachedInRange = await getCachedInRange(queryClient2, parquetPath, columnName, lo, hi);
|
|
372111
|
+
const betterLo = cachedInRange.slice().reverse().find((c2) => c2.index > lo && targetValue >= c2.max);
|
|
372112
|
+
if (betterLo) {
|
|
372113
|
+
lo = Math.min(hi, betterLo.index + 1);
|
|
372114
|
+
}
|
|
372115
|
+
const betterHi = cachedInRange.find((c2) => targetValue < c2.min);
|
|
372116
|
+
if (betterHi) {
|
|
372117
|
+
hi = Math.max(lo, betterHi.index - 1);
|
|
372118
|
+
}
|
|
372119
|
+
if (lo >= hi) {
|
|
372120
|
+
break;
|
|
372121
|
+
}
|
|
372122
|
+
const mid = Math.floor((lo + hi) / 2);
|
|
372123
|
+
const { max: midVal } = await _loadParquetRowGroupColumnExtent({ queryClient: queryClient2, store: store2 }, parquetPath, columnName, mid);
|
|
372124
|
+
if (midVal === null || targetValue <= midVal) {
|
|
372125
|
+
hi = mid;
|
|
372126
|
+
} else {
|
|
372127
|
+
lo = mid + 1;
|
|
372128
|
+
}
|
|
372129
|
+
}
|
|
372130
|
+
return lo;
|
|
372131
|
+
},
|
|
372132
|
+
meta: { queryClient, store }
|
|
372133
|
+
});
|
|
372134
|
+
}
|
|
372135
|
+
async function _rectToRowGroupIndices({ queryClient, store }, parquetPath, tileBbox, allPointsBbox) {
|
|
372136
|
+
return queryClient.fetchQuery({
|
|
372137
|
+
queryKey: ["SpatialDataTableSource", "_rectToRowGroupIndices", parquetPath, tileBbox, allPointsBbox],
|
|
372138
|
+
staleTime: Infinity,
|
|
372139
|
+
queryFn: async (ctx) => {
|
|
372140
|
+
const queryClient2 = (
|
|
372141
|
+
/** @type {QueryClient} */
|
|
372142
|
+
ctx.meta?.queryClient
|
|
372143
|
+
);
|
|
372144
|
+
const store2 = ctx.meta?.store;
|
|
372145
|
+
const mortonIntervals = sdataMortonQueryRectAux(allPointsBbox, [
|
|
372146
|
+
[tileBbox.left, tileBbox.top],
|
|
372147
|
+
// TODO: is this backwards (bottom/top)?
|
|
372148
|
+
[tileBbox.right, tileBbox.bottom]
|
|
372149
|
+
]);
|
|
372150
|
+
let coveredRowGroupIndices = [];
|
|
372151
|
+
const intervalsSpanMultipleRowGroups = async (startIndex, endIndex) => {
|
|
372152
|
+
if (startIndex > endIndex) {
|
|
372153
|
+
return [false, null];
|
|
372154
|
+
}
|
|
372155
|
+
const [startMin, startMax] = mortonIntervals[startIndex];
|
|
372156
|
+
const [endMin, endMax] = mortonIntervals[endIndex];
|
|
372157
|
+
const [rowGroupIndexMin, rowGroupIndexMax] = await Promise.all([
|
|
372158
|
+
_bisectRowGroupsRight({ queryClient: queryClient2, store: store2 }, parquetPath, "morton_code_2d", startMin),
|
|
372159
|
+
_bisectRowGroupsRight({ queryClient: queryClient2, store: store2 }, parquetPath, "morton_code_2d", endMax)
|
|
372160
|
+
]);
|
|
372161
|
+
if (rowGroupIndexMin === rowGroupIndexMax) {
|
|
372162
|
+
return [false, [rowGroupIndexMin]];
|
|
372163
|
+
}
|
|
372164
|
+
if (rowGroupIndexMin + 1 === rowGroupIndexMax || rowGroupIndexMin - 1 === rowGroupIndexMax) {
|
|
372165
|
+
return [false, [rowGroupIndexMin, rowGroupIndexMax]];
|
|
372166
|
+
}
|
|
372167
|
+
return [true, null];
|
|
372168
|
+
};
|
|
372169
|
+
const intervalIndicesToCheck = [[0, mortonIntervals.length - 1]];
|
|
372170
|
+
while (intervalIndicesToCheck.length > 0) {
|
|
372171
|
+
const [startIndex, endIndex] = intervalIndicesToCheck.pop();
|
|
372172
|
+
const [spansMultipleRowGroups, rowGroupIndices] = await intervalsSpanMultipleRowGroups(startIndex, endIndex);
|
|
372173
|
+
if (!spansMultipleRowGroups) {
|
|
372174
|
+
if (rowGroupIndices !== null) {
|
|
372175
|
+
coveredRowGroupIndices = coveredRowGroupIndices.concat(rowGroupIndices);
|
|
372176
|
+
}
|
|
372177
|
+
} else {
|
|
372178
|
+
if (startIndex === endIndex) {
|
|
372179
|
+
const [intervalMin, intervalMax] = mortonIntervals[startIndex];
|
|
372180
|
+
const [rowGroupIndexMin, rowGroupIndexMax] = await Promise.all([
|
|
372181
|
+
_bisectRowGroupsRight({ queryClient: queryClient2, store: store2 }, parquetPath, "morton_code_2d", intervalMin),
|
|
372182
|
+
_bisectRowGroupsRight({ queryClient: queryClient2, store: store2 }, parquetPath, "morton_code_2d", intervalMax)
|
|
372183
|
+
]);
|
|
372184
|
+
if (rowGroupIndexMin <= rowGroupIndexMax) {
|
|
372185
|
+
coveredRowGroupIndices = coveredRowGroupIndices.concat(range$e(rowGroupIndexMin, rowGroupIndexMax + 1));
|
|
372186
|
+
} else {
|
|
372187
|
+
coveredRowGroupIndices = coveredRowGroupIndices.concat(range$e(rowGroupIndexMax, rowGroupIndexMin + 1));
|
|
372188
|
+
}
|
|
372189
|
+
} else {
|
|
372190
|
+
const midIndex = Math.floor((startIndex + endIndex) / 2);
|
|
372191
|
+
intervalIndicesToCheck.push([startIndex, midIndex]);
|
|
372192
|
+
intervalIndicesToCheck.push([midIndex + 1, endIndex]);
|
|
372193
|
+
}
|
|
372194
|
+
}
|
|
372195
|
+
}
|
|
372196
|
+
const uniqueCoveredRowGroupIndices = Array.from(new Set(coveredRowGroupIndices));
|
|
372197
|
+
return uniqueCoveredRowGroupIndices;
|
|
372198
|
+
},
|
|
372199
|
+
meta: { queryClient, store }
|
|
372200
|
+
});
|
|
371215
372201
|
}
|
|
371216
372202
|
function tableToIndexColumnName(arrowTable) {
|
|
371217
372203
|
const pandasMetadata = arrowTable.schema.metadata.get("pandas");
|
|
@@ -371265,14 +372251,17 @@ function getVarPath(arrPath) {
|
|
|
371265
372251
|
class SpatialDataTableSource extends AnnDataSource {
|
|
371266
372252
|
/**
|
|
371267
372253
|
*
|
|
371268
|
-
* @param {DataSourceParams} params
|
|
372254
|
+
* @param {DataSourceParams & { queryClient: QueryClient }} params
|
|
371269
372255
|
*/
|
|
371270
372256
|
constructor(params2) {
|
|
371271
372257
|
super(params2);
|
|
372258
|
+
const { queryClient } = params2;
|
|
372259
|
+
this.queryClient = queryClient;
|
|
371272
372260
|
this.parquetModulePromise = getParquetModule();
|
|
371273
372261
|
this.rootAttrs = null;
|
|
371274
372262
|
this.elementAttrs = {};
|
|
371275
372263
|
this.parquetTableBytes = {};
|
|
372264
|
+
this.parquetTableIsDirectory = {};
|
|
371276
372265
|
this.obsIndices = {};
|
|
371277
372266
|
this.varIndices = {};
|
|
371278
372267
|
this.varAliases = {};
|
|
@@ -371326,17 +372315,19 @@ class SpatialDataTableSource extends AnnDataSource {
|
|
|
371326
372315
|
* relative to the store root.
|
|
371327
372316
|
* @returns {Promise<Uint8Array|undefined>} The parquet file bytes.
|
|
371328
372317
|
*/
|
|
371329
|
-
async loadParquetBytes(parquetPath) {
|
|
371330
|
-
|
|
371331
|
-
|
|
372318
|
+
async loadParquetBytes(parquetPath, offset2 = void 0, length2 = void 0, partIndex = void 0) {
|
|
372319
|
+
const { store } = this.storeRoot;
|
|
372320
|
+
let getter2 = (path2) => store.get(path2);
|
|
372321
|
+
if (offset2 !== void 0 && length2 !== void 0 && store.getRange) {
|
|
372322
|
+
getter2 = (path2) => store.getRange(path2, {
|
|
372323
|
+
offset: offset2,
|
|
372324
|
+
length: length2
|
|
372325
|
+
});
|
|
371332
372326
|
}
|
|
371333
|
-
let parquetBytes = await
|
|
372327
|
+
let parquetBytes = await getter2(`/${parquetPath}`);
|
|
371334
372328
|
if (!parquetBytes) {
|
|
371335
|
-
const part0Path = `${parquetPath}/part
|
|
371336
|
-
parquetBytes = await
|
|
371337
|
-
}
|
|
371338
|
-
if (parquetBytes) {
|
|
371339
|
-
this.parquetTableBytes[parquetPath] = parquetBytes;
|
|
372329
|
+
const part0Path = `${parquetPath}/part.${partIndex ?? 0}.parquet`;
|
|
372330
|
+
parquetBytes = await getter2(`/${part0Path}`);
|
|
371340
372331
|
}
|
|
371341
372332
|
return parquetBytes;
|
|
371342
372333
|
}
|
|
@@ -371355,7 +372346,7 @@ class SpatialDataTableSource extends AnnDataSource {
|
|
|
371355
372346
|
* @returns {Promise<Uint8Array|null>} The parquet file bytes,
|
|
371356
372347
|
* or null if the store does not support getRange.
|
|
371357
372348
|
*/
|
|
371358
|
-
async loadParquetSchemaBytes(parquetPath) {
|
|
372349
|
+
async loadParquetSchemaBytes(parquetPath, partIndex = void 0) {
|
|
371359
372350
|
const { store } = this.storeRoot;
|
|
371360
372351
|
if (store.getRange) {
|
|
371361
372352
|
const TAIL_LENGTH = 8;
|
|
@@ -371363,12 +372354,10 @@ class SpatialDataTableSource extends AnnDataSource {
|
|
|
371363
372354
|
let tailBytes = await store.getRange(`/${partZeroPath}`, {
|
|
371364
372355
|
suffixLength: TAIL_LENGTH
|
|
371365
372356
|
});
|
|
371366
|
-
|
|
371367
|
-
|
|
371368
|
-
|
|
371369
|
-
|
|
371370
|
-
});
|
|
371371
|
-
}
|
|
372357
|
+
partZeroPath = `${parquetPath}/part.${partIndex ?? 0}.parquet`;
|
|
372358
|
+
tailBytes = await store.getRange(`/${partZeroPath}`, {
|
|
372359
|
+
suffixLength: TAIL_LENGTH
|
|
372360
|
+
});
|
|
371372
372361
|
if (!tailBytes || tailBytes.length < TAIL_LENGTH) {
|
|
371373
372362
|
throw new Error(`Failed to load parquet footerLength for ${parquetPath}`);
|
|
371374
372363
|
}
|
|
@@ -371430,7 +372419,7 @@ class SpatialDataTableSource extends AnnDataSource {
|
|
|
371430
372419
|
const schemaBytes = await this.loadParquetSchemaBytes(parquetPath);
|
|
371431
372420
|
if (schemaBytes) {
|
|
371432
372421
|
const wasmSchema = readSchema(schemaBytes);
|
|
371433
|
-
const arrowTableForSchema =
|
|
372422
|
+
const arrowTableForSchema = tableFromIPC(wasmSchema.intoIPCStream());
|
|
371434
372423
|
indexColumnName = tableToIndexColumnName(arrowTableForSchema);
|
|
371435
372424
|
}
|
|
371436
372425
|
} catch (e3) {
|
|
@@ -371446,14 +372435,14 @@ class SpatialDataTableSource extends AnnDataSource {
|
|
|
371446
372435
|
}
|
|
371447
372436
|
if (columns2 && !indexColumnName) {
|
|
371448
372437
|
const wasmSchema = readSchema(parquetBytes);
|
|
371449
|
-
const arrowTableForSchema =
|
|
372438
|
+
const arrowTableForSchema = tableFromIPC(wasmSchema.intoIPCStream());
|
|
371450
372439
|
indexColumnName = tableToIndexColumnName(arrowTableForSchema);
|
|
371451
372440
|
}
|
|
371452
372441
|
if (options.columns && indexColumnName) {
|
|
371453
372442
|
options.columns = [...options.columns, indexColumnName];
|
|
371454
372443
|
}
|
|
371455
372444
|
const wasmTable = readParquet(parquetBytes, options);
|
|
371456
|
-
const arrowTable =
|
|
372445
|
+
const arrowTable = tableFromIPC(wasmTable.intoIPCStream());
|
|
371457
372446
|
return arrowTable;
|
|
371458
372447
|
}
|
|
371459
372448
|
// TABLE-SPECIFIC METHODS
|
|
@@ -371517,6 +372506,93 @@ class SpatialDataTableSource extends AnnDataSource {
|
|
|
371517
372506
|
this.varAliases[varPath] = this.varAliases[varPath].map((val, ind) => val ? val.concat(` (${index2[ind]})`) : index2[ind]);
|
|
371518
372507
|
return this.varAliases[varPath];
|
|
371519
372508
|
}
|
|
372509
|
+
async _supportsTiledPoints(parquetPath) {
|
|
372510
|
+
const { queryClient } = this;
|
|
372511
|
+
const { store } = this.storeRoot;
|
|
372512
|
+
const allMetadata = await _loadParquetMetadataByPart({ queryClient, store }, parquetPath);
|
|
372513
|
+
const { numRowsPerGroup } = allMetadata;
|
|
372514
|
+
const numRowsTotal = allMetadata.numRows;
|
|
372515
|
+
if (numRowsPerGroup >= 1e5) {
|
|
372516
|
+
if (numRowsTotal > 5e6) {
|
|
372517
|
+
throw new Error(`The Parquet table at ${parquetPath} has ${numRowsTotal} total rows, which necessitates tiled loading, but it was not possible because the row group size is too large (${numRowsPerGroup}). See the Vitessce documentation at Data Troubleshooting -> Points for more details.`);
|
|
372518
|
+
}
|
|
372519
|
+
return false;
|
|
372520
|
+
}
|
|
372521
|
+
const requiredColumns = ["x", "y", "feature_index", "morton_code_2d"];
|
|
372522
|
+
const hasColumns = allMetadata?.schema?.fields?.map((f2) => f2.name);
|
|
372523
|
+
if (!hasColumns) {
|
|
372524
|
+
return false;
|
|
372525
|
+
}
|
|
372526
|
+
const hasRequiredColumns = requiredColumns.every((col) => hasColumns.includes(col));
|
|
372527
|
+
if (!hasRequiredColumns && numRowsTotal > 5e6) {
|
|
372528
|
+
throw new Error(`The Parquet table at ${parquetPath} has ${numRowsTotal} total rows, which necessitates tiled loading, but it was not possible because the required columns are missing. Required columns: ${requiredColumns.join(", ")}. Found columns: ${hasColumns.join(", ")}. See the Vitessce documentation at Data Troubleshooting -> Points for more details.`);
|
|
372529
|
+
}
|
|
372530
|
+
return hasRequiredColumns;
|
|
372531
|
+
}
|
|
372532
|
+
/**
|
|
372533
|
+
* Load point data using a tiled approach.
|
|
372534
|
+
* @param {string} parquetPath A path to a parquet file (or directory).
|
|
372535
|
+
* @param {{ left: number, top: number, right: number, bottom: number }} tileBbox
|
|
372536
|
+
* @param {{ x_min: number, y_min: number, x_max: number, y_max: number }} allPointsBbox
|
|
372537
|
+
* @param {string[]|undefined} columns An optional list of column names to load.
|
|
372538
|
+
* @returns
|
|
372539
|
+
*/
|
|
372540
|
+
async loadParquetTableInRect(parquetPath, tileBbox, allPointsBbox, signal) {
|
|
372541
|
+
const { queryClient } = this;
|
|
372542
|
+
const { store } = this.storeRoot;
|
|
372543
|
+
const TILE_SIZE2 = 256;
|
|
372544
|
+
let tileBboxes = [];
|
|
372545
|
+
if (tileBbox.right - tileBbox.left > TILE_SIZE2 || tileBbox.bottom - tileBbox.top > TILE_SIZE2) {
|
|
372546
|
+
const xSteps = Math.ceil((tileBbox.right - tileBbox.left) / TILE_SIZE2);
|
|
372547
|
+
const ySteps = Math.ceil((tileBbox.bottom - tileBbox.top) / TILE_SIZE2);
|
|
372548
|
+
const xStepSize = (tileBbox.right - tileBbox.left) / xSteps;
|
|
372549
|
+
const yStepSize = (tileBbox.bottom - tileBbox.top) / ySteps;
|
|
372550
|
+
for (let i2 = 0; i2 < xSteps; i2++) {
|
|
372551
|
+
for (let j = 0; j < ySteps; j++) {
|
|
372552
|
+
const subTileBbox = {
|
|
372553
|
+
left: tileBbox.left + i2 * xStepSize,
|
|
372554
|
+
right: Math.min(tileBbox.left + (i2 + 1) * xStepSize, tileBbox.right),
|
|
372555
|
+
top: tileBbox.top + j * yStepSize,
|
|
372556
|
+
bottom: Math.min(tileBbox.top + (j + 1) * yStepSize, tileBbox.bottom)
|
|
372557
|
+
};
|
|
372558
|
+
tileBboxes.push(subTileBbox);
|
|
372559
|
+
}
|
|
372560
|
+
}
|
|
372561
|
+
} else {
|
|
372562
|
+
tileBboxes = [tileBbox];
|
|
372563
|
+
}
|
|
372564
|
+
const rowGroupIndicesPerTile = await Promise.all(tileBboxes.map(async (subTileBbox) => _rectToRowGroupIndices({ queryClient, store }, parquetPath, subTileBbox, allPointsBbox)));
|
|
372565
|
+
const uniqueCoveredRowGroupIndices = Array.from(new Set(rowGroupIndicesPerTile.flat())).toSorted((a2, b2) => a2 - b2);
|
|
372566
|
+
const allMetadata = await _loadParquetMetadataByPart({ queryClient, store }, parquetPath);
|
|
372567
|
+
const { numRowsPerGroup } = allMetadata;
|
|
372568
|
+
const numRowGroups = uniqueCoveredRowGroupIndices.length;
|
|
372569
|
+
const totalNumRows = numRowsPerGroup * numRowGroups;
|
|
372570
|
+
const xArr = new Float32Array(totalNumRows);
|
|
372571
|
+
const yArr = new Float32Array(totalNumRows);
|
|
372572
|
+
const featureIndexArr = new Uint32Array(totalNumRows);
|
|
372573
|
+
const rowGroupTables = await Promise.all(uniqueCoveredRowGroupIndices.map(async (rowGroupIndex) => _loadParquetRowGroupByGroupIndex({ queryClient, store }, parquetPath, rowGroupIndex)));
|
|
372574
|
+
let rowOffset = 0;
|
|
372575
|
+
rowGroupTables.forEach((table2) => {
|
|
372576
|
+
const xColumn = table2.getChild("x");
|
|
372577
|
+
const yColumn = table2.getChild("y");
|
|
372578
|
+
const featureIndexColumn = table2.getChild("feature_index");
|
|
372579
|
+
if (!xColumn || !yColumn || !featureIndexColumn) {
|
|
372580
|
+
throw new Error(`Missing required column in parquet table at ${parquetPath}. Required columns: x, y, feature_index`);
|
|
372581
|
+
}
|
|
372582
|
+
xArr.set(xColumn.toArray(), rowOffset);
|
|
372583
|
+
yArr.set(yColumn.toArray(), rowOffset);
|
|
372584
|
+
featureIndexArr.set(featureIndexColumn.toArray(), rowOffset);
|
|
372585
|
+
rowOffset += numRowsPerGroup;
|
|
372586
|
+
});
|
|
372587
|
+
return {
|
|
372588
|
+
data: {
|
|
372589
|
+
x: xArr,
|
|
372590
|
+
y: yArr,
|
|
372591
|
+
featureIndices: featureIndexArr
|
|
372592
|
+
},
|
|
372593
|
+
shape: [3, totalNumRows]
|
|
372594
|
+
};
|
|
372595
|
+
}
|
|
371520
372596
|
}
|
|
371521
372597
|
class BaseEvent {
|
|
371522
372598
|
/**
|
|
@@ -377672,6 +378748,33 @@ class SpatialDataPointsSource extends SpatialDataTableSource {
|
|
|
377672
378748
|
data: axisColumnArrs
|
|
377673
378749
|
};
|
|
377674
378750
|
}
|
|
378751
|
+
/**
|
|
378752
|
+
*
|
|
378753
|
+
* @param {string} elementPath
|
|
378754
|
+
* @param {{ left: number, top: number, right: number, bottom: number }} tileBbox
|
|
378755
|
+
* @returns {Promise<{
|
|
378756
|
+
* data: [ZarrTypedArray<any>, ZarrTypedArray<any>],
|
|
378757
|
+
* shape: [number, number],
|
|
378758
|
+
* }>} A promise for a zarr array containing the data.
|
|
378759
|
+
*/
|
|
378760
|
+
async loadPointsInRect(elementPath, tileBbox, signal) {
|
|
378761
|
+
const parquetPath = getParquetPath(elementPath);
|
|
378762
|
+
const zattrs = await this.loadSpatialDataElementAttrs(elementPath);
|
|
378763
|
+
const {
|
|
378764
|
+
// axes,
|
|
378765
|
+
// spatialdata_attrs: spatialDataAttrs,
|
|
378766
|
+
// The bounding box (extent) of all points.
|
|
378767
|
+
// Required for un-normalization from uints back to floats.
|
|
378768
|
+
// TODO: decide whether these will be stored here or somewhere else.
|
|
378769
|
+
// Reference: https://github.com/vitessce/vitessce-python/pull/476#issuecomment-3362656956
|
|
378770
|
+
bounding_box: allPointsBbox
|
|
378771
|
+
} = zattrs;
|
|
378772
|
+
return this.loadParquetTableInRect(parquetPath, tileBbox, allPointsBbox, signal);
|
|
378773
|
+
}
|
|
378774
|
+
async supportsLoadPointsInRect(elementPath) {
|
|
378775
|
+
const parquetPath = getParquetPath(elementPath);
|
|
378776
|
+
return this._supportsTiledPoints(parquetPath);
|
|
378777
|
+
}
|
|
377675
378778
|
}
|
|
377676
378779
|
class OmeTiffSource {
|
|
377677
378780
|
constructor({ url, requestInit: requestInit2 }) {
|
|
@@ -383776,7 +384879,20 @@ const baseCoordinationTypes = [
|
|
|
383776
384879
|
path: obsSetPath,
|
|
383777
384880
|
color: rgbArray
|
|
383778
384881
|
})).nullable()),
|
|
383779
|
-
new PluginCoordinationType(CoordinationType$1.
|
|
384882
|
+
new PluginCoordinationType(CoordinationType$1.FEATURE_COLOR, null, z.array(z.object({
|
|
384883
|
+
name: z.string(),
|
|
384884
|
+
color: rgbArray
|
|
384885
|
+
})).nullable()),
|
|
384886
|
+
new PluginCoordinationType(CoordinationType$1.OBS_COLOR_ENCODING, "cellSetSelection", z.enum([
|
|
384887
|
+
"geneSelection",
|
|
384888
|
+
"cellSetSelection",
|
|
384889
|
+
"spatialChannelColor",
|
|
384890
|
+
"spatialLayerColor",
|
|
384891
|
+
"obsLabels",
|
|
384892
|
+
// For point coloring.
|
|
384893
|
+
"random",
|
|
384894
|
+
"randomByFeature"
|
|
384895
|
+
])),
|
|
383780
384896
|
new PluginCoordinationType(CoordinationType$1.FEATURE_FILTER, null, z.array(z.string()).nullable()),
|
|
383781
384897
|
new PluginCoordinationType(CoordinationType$1.FEATURE_HIGHLIGHT, null, z.string().nullable()),
|
|
383782
384898
|
new PluginCoordinationType(CoordinationType$1.FEATURE_SELECTION, null, z.array(z.string()).nullable()),
|
|
@@ -383794,7 +384910,7 @@ const baseCoordinationTypes = [
|
|
|
383794
384910
|
new PluginCoordinationType(CoordinationType$1.FEATURE_SET_SELECTION, null, z.array(obsSetPath).nullable()),
|
|
383795
384911
|
new PluginCoordinationType(CoordinationType$1.FEATURE_SELECTION_MODE, null, z.enum(["featureSelection", "featureSetSelection"]).nullable()),
|
|
383796
384912
|
new PluginCoordinationType(CoordinationType$1.FEATURE_SET_FILTER, null, z.array(obsSetPath).nullable()),
|
|
383797
|
-
new PluginCoordinationType(CoordinationType$1.FEATURE_FILTER_MODE, null, z.enum(["featureFilter", "featureSetFilter"]).nullable()),
|
|
384913
|
+
new PluginCoordinationType(CoordinationType$1.FEATURE_FILTER_MODE, null, z.enum(["featureFilter", "featureSetFilter", "featureSelection"]).nullable()),
|
|
383798
384914
|
new PluginCoordinationType(CoordinationType$1.FEATURE_VALUE_TRANSFORM, null, z.enum(["log1p", "arcsinh"]).nullable()),
|
|
383799
384915
|
new PluginCoordinationType(CoordinationType$1.FEATURE_VALUE_TRANSFORM_COEFFICIENT, 1, z.number()),
|
|
383800
384916
|
new PluginCoordinationType(CoordinationType$1.FEATURE_VALUE_POSITIVITY_THRESHOLD, 0, z.number()),
|