@vitessce/all 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-Bq0h_Ctg.js → OrbitControls-B2DZt-9I.js} +1 -1
- package/dist/{ReactNeuroglancer-D9Izf3YW.js → ReactNeuroglancer-rd4zjvRk.js} +1 -1
- package/dist/{deflate-qFZzl85K.js → deflate-mmlLWSqG.js} +1 -1
- package/dist/{higlass-CtfTtjGe.js → higlass-Chx9S58D.js} +1 -1
- package/dist/{index-B0JyLhTY.js → index-Ccs0RkVq.js} +1335 -215
- package/dist/{index-DZg7IgTe.js → index-SH4i0VjQ.js} +3 -3
- package/dist/{index-eU9RLuKQ.js → index-gdPd0Ws9.js} +2 -2
- package/dist/index.js +1 -1
- package/dist/{jpeg-BOKb2qaL.js → jpeg-C90IvgAr.js} +1 -1
- package/dist/{lerc-CBp5l3Pw.js → lerc-cm5d7rjy.js} +1 -1
- package/dist/{lzw-CkA9e76s.js → lzw-BNtf5UsG.js} +1 -1
- package/dist/{packbits-DOr_NbG_.js → packbits-BaMXgBB6.js} +1 -1
- package/dist/{raw-BEDGxpo9.js → raw-C5wVKuiu.js} +1 -1
- package/dist/{troika-three-text.esm-aenn8tL8.js → troika-three-text.esm-D_LuNiSc.js} +1 -1
- package/dist/{webimage-Ad_VhFBm.js → webimage-BjAUnP6y.js} +1 -1
- package/dist-tsc/base-plugins.d.ts +10 -1
- package/dist-tsc/base-plugins.d.ts.map +1 -1
- package/dist-tsc/base-plugins.js +10 -2
- package/package.json +33 -33
- package/src/base-plugins.ts +14 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import React__default, { useContext, forwardRef as forwardRef$1, useRef, useMemo as useMemo$1, createContext, createElement, isValidElement, cloneElement, Children, version as version$6, useLayoutEffect as useLayoutEffect$1, useEffect, useImperativeHandle, PureComponent, Component as Component$1, useState, useCallback, 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 } 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 } 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) {
|
|
@@ -9354,6 +9354,7 @@ const CoordinationType$1 = {
|
|
|
9354
9354
|
OBS_SET_HIGHLIGHT: "obsSetHighlight",
|
|
9355
9355
|
OBS_SET_EXPANSION: "obsSetExpansion",
|
|
9356
9356
|
OBS_SET_COLOR: "obsSetColor",
|
|
9357
|
+
FEATURE_COLOR: "featureColor",
|
|
9357
9358
|
FEATURE_HIGHLIGHT: "featureHighlight",
|
|
9358
9359
|
FEATURE_SELECTION: "featureSelection",
|
|
9359
9360
|
FEATURE_SET_SELECTION: "featureSetSelection",
|
|
@@ -9958,6 +9959,8 @@ const COMPONENT_COORDINATION_TYPES = {
|
|
|
9958
9959
|
CoordinationType$1.OBS_SET_FILTER,
|
|
9959
9960
|
CoordinationType$1.OBS_SET_HIGHLIGHT,
|
|
9960
9961
|
CoordinationType$1.OBS_SET_COLOR,
|
|
9962
|
+
CoordinationType$1.FEATURE_COLOR,
|
|
9963
|
+
CoordinationType$1.FEATURE_FILTER_MODE,
|
|
9961
9964
|
CoordinationType$1.FEATURE_HIGHLIGHT,
|
|
9962
9965
|
CoordinationType$1.FEATURE_SELECTION,
|
|
9963
9966
|
CoordinationType$1.FEATURE_VALUE_COLORMAP,
|
|
@@ -10172,6 +10175,8 @@ const COMPONENT_COORDINATION_TYPES = {
|
|
|
10172
10175
|
CoordinationType$1.SPATIAL_SPOT_STROKE_WIDTH,
|
|
10173
10176
|
CoordinationType$1.SPATIAL_LAYER_COLOR,
|
|
10174
10177
|
CoordinationType$1.OBS_COLOR_ENCODING,
|
|
10178
|
+
CoordinationType$1.FEATURE_COLOR,
|
|
10179
|
+
CoordinationType$1.FEATURE_FILTER_MODE,
|
|
10175
10180
|
CoordinationType$1.FEATURE_VALUE_COLORMAP,
|
|
10176
10181
|
CoordinationType$1.FEATURE_VALUE_COLORMAP_RANGE,
|
|
10177
10182
|
CoordinationType$1.FEATURE_SELECTION,
|
|
@@ -31993,7 +31998,7 @@ var _span$3;
|
|
|
31993
31998
|
const useUtilityClasses$1h = (ownerState) => {
|
|
31994
31999
|
const {
|
|
31995
32000
|
classes: classes2,
|
|
31996
|
-
contained,
|
|
32001
|
+
contained: contained2,
|
|
31997
32002
|
size: size2,
|
|
31998
32003
|
disabled,
|
|
31999
32004
|
error: error2,
|
|
@@ -32002,7 +32007,7 @@ const useUtilityClasses$1h = (ownerState) => {
|
|
|
32002
32007
|
required: required2
|
|
32003
32008
|
} = ownerState;
|
|
32004
32009
|
const slots = {
|
|
32005
|
-
root: ["root", disabled && "disabled", error2 && "error", size2 && `size${capitalize$1(size2)}`,
|
|
32010
|
+
root: ["root", disabled && "disabled", error2 && "error", size2 && `size${capitalize$1(size2)}`, contained2 && "contained", focused && "focused", filled && "filled", required2 && "required"]
|
|
32006
32011
|
};
|
|
32007
32012
|
return composeClasses(slots, getFormHelperTextUtilityClasses, classes2);
|
|
32008
32013
|
};
|
|
@@ -33495,6 +33500,90 @@ ListItemText.propTypes = {
|
|
|
33495
33500
|
*/
|
|
33496
33501
|
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])
|
|
33497
33502
|
};
|
|
33503
|
+
function getListItemIconUtilityClass(slot) {
|
|
33504
|
+
return generateUtilityClass("MuiListItemIcon", slot);
|
|
33505
|
+
}
|
|
33506
|
+
const listItemIconClasses = generateUtilityClasses("MuiListItemIcon", ["root", "alignItemsFlexStart"]);
|
|
33507
|
+
const useUtilityClasses$1b = (ownerState) => {
|
|
33508
|
+
const {
|
|
33509
|
+
alignItems,
|
|
33510
|
+
classes: classes2
|
|
33511
|
+
} = ownerState;
|
|
33512
|
+
const slots = {
|
|
33513
|
+
root: ["root", alignItems === "flex-start" && "alignItemsFlexStart"]
|
|
33514
|
+
};
|
|
33515
|
+
return composeClasses(slots, getListItemIconUtilityClass, classes2);
|
|
33516
|
+
};
|
|
33517
|
+
const ListItemIconRoot = styled("div", {
|
|
33518
|
+
name: "MuiListItemIcon",
|
|
33519
|
+
slot: "Root",
|
|
33520
|
+
overridesResolver: (props, styles2) => {
|
|
33521
|
+
const {
|
|
33522
|
+
ownerState
|
|
33523
|
+
} = props;
|
|
33524
|
+
return [styles2.root, ownerState.alignItems === "flex-start" && styles2.alignItemsFlexStart];
|
|
33525
|
+
}
|
|
33526
|
+
})(memoTheme(({
|
|
33527
|
+
theme
|
|
33528
|
+
}) => ({
|
|
33529
|
+
minWidth: 56,
|
|
33530
|
+
color: (theme.vars || theme).palette.action.active,
|
|
33531
|
+
flexShrink: 0,
|
|
33532
|
+
display: "inline-flex",
|
|
33533
|
+
variants: [{
|
|
33534
|
+
props: {
|
|
33535
|
+
alignItems: "flex-start"
|
|
33536
|
+
},
|
|
33537
|
+
style: {
|
|
33538
|
+
marginTop: 8
|
|
33539
|
+
}
|
|
33540
|
+
}]
|
|
33541
|
+
})));
|
|
33542
|
+
const ListItemIcon = /* @__PURE__ */ React.forwardRef(function ListItemIcon2(inProps, ref2) {
|
|
33543
|
+
const props = useDefaultProps({
|
|
33544
|
+
props: inProps,
|
|
33545
|
+
name: "MuiListItemIcon"
|
|
33546
|
+
});
|
|
33547
|
+
const {
|
|
33548
|
+
className,
|
|
33549
|
+
...other
|
|
33550
|
+
} = props;
|
|
33551
|
+
const context2 = React.useContext(ListContext);
|
|
33552
|
+
const ownerState = {
|
|
33553
|
+
...props,
|
|
33554
|
+
alignItems: context2.alignItems
|
|
33555
|
+
};
|
|
33556
|
+
const classes2 = useUtilityClasses$1b(ownerState);
|
|
33557
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(ListItemIconRoot, {
|
|
33558
|
+
className: clsx$1(classes2.root, className),
|
|
33559
|
+
ownerState,
|
|
33560
|
+
ref: ref2,
|
|
33561
|
+
...other
|
|
33562
|
+
});
|
|
33563
|
+
});
|
|
33564
|
+
ListItemIcon.propTypes = {
|
|
33565
|
+
// ┌────────────────────────────── Warning ──────────────────────────────┐
|
|
33566
|
+
// │ These PropTypes are generated from the TypeScript type definitions. │
|
|
33567
|
+
// │ To update them, edit the d.ts file and run `pnpm proptypes`. │
|
|
33568
|
+
// └─────────────────────────────────────────────────────────────────────┘
|
|
33569
|
+
/**
|
|
33570
|
+
* The content of the component, normally `Icon`, `SvgIcon`,
|
|
33571
|
+
* or a `@mui/icons-material` SVG icon element.
|
|
33572
|
+
*/
|
|
33573
|
+
children: PropTypes.node,
|
|
33574
|
+
/**
|
|
33575
|
+
* Override or extend the styles applied to the component.
|
|
33576
|
+
*/
|
|
33577
|
+
classes: PropTypes.object,
|
|
33578
|
+
/**
|
|
33579
|
+
* @ignore
|
|
33580
|
+
*/
|
|
33581
|
+
className: PropTypes.string,
|
|
33582
|
+
/**
|
|
33583
|
+
* The system prop that allows defining system overrides as well as additional CSS styles.
|
|
33584
|
+
*/
|
|
33585
|
+
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])
|
|
33586
|
+
};
|
|
33498
33587
|
function getScrollbarSize$1(win2 = window) {
|
|
33499
33588
|
const documentWidth = win2.document.documentElement.clientWidth;
|
|
33500
33589
|
return win2.innerWidth - documentWidth;
|
|
@@ -33746,7 +33835,7 @@ function getDividerUtilityClass(slot) {
|
|
|
33746
33835
|
return generateUtilityClass("MuiDivider", slot);
|
|
33747
33836
|
}
|
|
33748
33837
|
const dividerClasses = generateUtilityClasses("MuiDivider", ["root", "absolute", "fullWidth", "inset", "middle", "flexItem", "light", "vertical", "withChildren", "withChildrenVertical", "textAlignRight", "textAlignLeft", "wrapper", "wrapperVertical"]);
|
|
33749
|
-
const useUtilityClasses$
|
|
33838
|
+
const useUtilityClasses$1a = (ownerState) => {
|
|
33750
33839
|
const {
|
|
33751
33840
|
absolute: absolute2,
|
|
33752
33841
|
children: children3,
|
|
@@ -33960,7 +34049,7 @@ const Divider$1 = /* @__PURE__ */ React.forwardRef(function Divider2(inProps, re
|
|
|
33960
34049
|
textAlign: textAlign2,
|
|
33961
34050
|
variant
|
|
33962
34051
|
};
|
|
33963
|
-
const classes2 = useUtilityClasses$
|
|
34052
|
+
const classes2 = useUtilityClasses$1a(ownerState);
|
|
33964
34053
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(DividerRoot, {
|
|
33965
34054
|
as: component,
|
|
33966
34055
|
className: clsx$1(classes2.root, className),
|
|
@@ -34042,90 +34131,6 @@ Divider$1.propTypes = {
|
|
|
34042
34131
|
*/
|
|
34043
34132
|
variant: PropTypes.oneOfType([PropTypes.oneOf(["fullWidth", "inset", "middle"]), PropTypes.string])
|
|
34044
34133
|
};
|
|
34045
|
-
function getListItemIconUtilityClass(slot) {
|
|
34046
|
-
return generateUtilityClass("MuiListItemIcon", slot);
|
|
34047
|
-
}
|
|
34048
|
-
const listItemIconClasses = generateUtilityClasses("MuiListItemIcon", ["root", "alignItemsFlexStart"]);
|
|
34049
|
-
const useUtilityClasses$1a = (ownerState) => {
|
|
34050
|
-
const {
|
|
34051
|
-
alignItems,
|
|
34052
|
-
classes: classes2
|
|
34053
|
-
} = ownerState;
|
|
34054
|
-
const slots = {
|
|
34055
|
-
root: ["root", alignItems === "flex-start" && "alignItemsFlexStart"]
|
|
34056
|
-
};
|
|
34057
|
-
return composeClasses(slots, getListItemIconUtilityClass, classes2);
|
|
34058
|
-
};
|
|
34059
|
-
const ListItemIconRoot = styled("div", {
|
|
34060
|
-
name: "MuiListItemIcon",
|
|
34061
|
-
slot: "Root",
|
|
34062
|
-
overridesResolver: (props, styles2) => {
|
|
34063
|
-
const {
|
|
34064
|
-
ownerState
|
|
34065
|
-
} = props;
|
|
34066
|
-
return [styles2.root, ownerState.alignItems === "flex-start" && styles2.alignItemsFlexStart];
|
|
34067
|
-
}
|
|
34068
|
-
})(memoTheme(({
|
|
34069
|
-
theme
|
|
34070
|
-
}) => ({
|
|
34071
|
-
minWidth: 56,
|
|
34072
|
-
color: (theme.vars || theme).palette.action.active,
|
|
34073
|
-
flexShrink: 0,
|
|
34074
|
-
display: "inline-flex",
|
|
34075
|
-
variants: [{
|
|
34076
|
-
props: {
|
|
34077
|
-
alignItems: "flex-start"
|
|
34078
|
-
},
|
|
34079
|
-
style: {
|
|
34080
|
-
marginTop: 8
|
|
34081
|
-
}
|
|
34082
|
-
}]
|
|
34083
|
-
})));
|
|
34084
|
-
const ListItemIcon = /* @__PURE__ */ React.forwardRef(function ListItemIcon2(inProps, ref2) {
|
|
34085
|
-
const props = useDefaultProps({
|
|
34086
|
-
props: inProps,
|
|
34087
|
-
name: "MuiListItemIcon"
|
|
34088
|
-
});
|
|
34089
|
-
const {
|
|
34090
|
-
className,
|
|
34091
|
-
...other
|
|
34092
|
-
} = props;
|
|
34093
|
-
const context2 = React.useContext(ListContext);
|
|
34094
|
-
const ownerState = {
|
|
34095
|
-
...props,
|
|
34096
|
-
alignItems: context2.alignItems
|
|
34097
|
-
};
|
|
34098
|
-
const classes2 = useUtilityClasses$1a(ownerState);
|
|
34099
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(ListItemIconRoot, {
|
|
34100
|
-
className: clsx$1(classes2.root, className),
|
|
34101
|
-
ownerState,
|
|
34102
|
-
ref: ref2,
|
|
34103
|
-
...other
|
|
34104
|
-
});
|
|
34105
|
-
});
|
|
34106
|
-
ListItemIcon.propTypes = {
|
|
34107
|
-
// ┌────────────────────────────── Warning ──────────────────────────────┐
|
|
34108
|
-
// │ These PropTypes are generated from the TypeScript type definitions. │
|
|
34109
|
-
// │ To update them, edit the d.ts file and run `pnpm proptypes`. │
|
|
34110
|
-
// └─────────────────────────────────────────────────────────────────────┘
|
|
34111
|
-
/**
|
|
34112
|
-
* The content of the component, normally `Icon`, `SvgIcon`,
|
|
34113
|
-
* or a `@mui/icons-material` SVG icon element.
|
|
34114
|
-
*/
|
|
34115
|
-
children: PropTypes.node,
|
|
34116
|
-
/**
|
|
34117
|
-
* Override or extend the styles applied to the component.
|
|
34118
|
-
*/
|
|
34119
|
-
classes: PropTypes.object,
|
|
34120
|
-
/**
|
|
34121
|
-
* @ignore
|
|
34122
|
-
*/
|
|
34123
|
-
className: PropTypes.string,
|
|
34124
|
-
/**
|
|
34125
|
-
* The system prop that allows defining system overrides as well as additional CSS styles.
|
|
34126
|
-
*/
|
|
34127
|
-
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])
|
|
34128
|
-
};
|
|
34129
34134
|
function getMenuItemUtilityClass(slot) {
|
|
34130
34135
|
return generateUtilityClass("MuiMenuItem", slot);
|
|
34131
34136
|
}
|
|
@@ -169936,14 +169941,14 @@ class RBush {
|
|
|
169936
169941
|
search(bbox2) {
|
|
169937
169942
|
let node2 = this.data;
|
|
169938
169943
|
const result = [];
|
|
169939
|
-
if (!intersects$
|
|
169944
|
+
if (!intersects$4(bbox2, node2)) return result;
|
|
169940
169945
|
const toBBox = this.toBBox;
|
|
169941
169946
|
const nodesToSearch = [];
|
|
169942
169947
|
while (node2) {
|
|
169943
169948
|
for (let i2 = 0; i2 < node2.children.length; i2++) {
|
|
169944
169949
|
const child = node2.children[i2];
|
|
169945
169950
|
const childBBox = node2.leaf ? toBBox(child) : child;
|
|
169946
|
-
if (intersects$
|
|
169951
|
+
if (intersects$4(bbox2, childBBox)) {
|
|
169947
169952
|
if (node2.leaf) result.push(child);
|
|
169948
169953
|
else if (contains$3(bbox2, childBBox)) this._all(child, result);
|
|
169949
169954
|
else nodesToSearch.push(child);
|
|
@@ -169955,13 +169960,13 @@ class RBush {
|
|
|
169955
169960
|
}
|
|
169956
169961
|
collides(bbox2) {
|
|
169957
169962
|
let node2 = this.data;
|
|
169958
|
-
if (!intersects$
|
|
169963
|
+
if (!intersects$4(bbox2, node2)) return false;
|
|
169959
169964
|
const nodesToSearch = [];
|
|
169960
169965
|
while (node2) {
|
|
169961
169966
|
for (let i2 = 0; i2 < node2.children.length; i2++) {
|
|
169962
169967
|
const child = node2.children[i2];
|
|
169963
169968
|
const childBBox = node2.leaf ? this.toBBox(child) : child;
|
|
169964
|
-
if (intersects$
|
|
169969
|
+
if (intersects$4(bbox2, childBBox)) {
|
|
169965
169970
|
if (node2.leaf || contains$3(bbox2, childBBox)) return true;
|
|
169966
169971
|
nodesToSearch.push(child);
|
|
169967
169972
|
}
|
|
@@ -170273,7 +170278,7 @@ function intersectionArea(a2, b2) {
|
|
|
170273
170278
|
function contains$3(a2, b2) {
|
|
170274
170279
|
return a2.minX <= b2.minX && a2.minY <= b2.minY && b2.maxX <= a2.maxX && b2.maxY <= a2.maxY;
|
|
170275
170280
|
}
|
|
170276
|
-
function intersects$
|
|
170281
|
+
function intersects$4(a2, b2) {
|
|
170277
170282
|
return b2.minX <= a2.maxX && b2.minY <= a2.maxY && b2.maxX >= a2.minX && b2.maxY >= a2.minY;
|
|
170278
170283
|
}
|
|
170279
170284
|
function createNode(children3) {
|
|
@@ -209135,22 +209140,22 @@ async function getDecoder(fileDirectory) {
|
|
|
209135
209140
|
const Decoder = await importFn();
|
|
209136
209141
|
return new Decoder(fileDirectory);
|
|
209137
209142
|
}
|
|
209138
|
-
addDecoder([void 0, 1], () => import("./raw-
|
|
209139
|
-
addDecoder(5, () => import("./lzw-
|
|
209143
|
+
addDecoder([void 0, 1], () => import("./raw-C5wVKuiu.js").then((m2) => m2.default));
|
|
209144
|
+
addDecoder(5, () => import("./lzw-BNtf5UsG.js").then((m2) => m2.default));
|
|
209140
209145
|
addDecoder(6, () => {
|
|
209141
209146
|
throw new Error("old style JPEG compression is not supported.");
|
|
209142
209147
|
});
|
|
209143
|
-
addDecoder(7, () => import("./jpeg-
|
|
209144
|
-
addDecoder([8, 32946], () => import("./deflate-
|
|
209145
|
-
addDecoder(32773, () => import("./packbits-
|
|
209148
|
+
addDecoder(7, () => import("./jpeg-C90IvgAr.js").then((m2) => m2.default));
|
|
209149
|
+
addDecoder([8, 32946], () => import("./deflate-mmlLWSqG.js").then((m2) => m2.default));
|
|
209150
|
+
addDecoder(32773, () => import("./packbits-BaMXgBB6.js").then((m2) => m2.default));
|
|
209146
209151
|
addDecoder(
|
|
209147
209152
|
34887,
|
|
209148
|
-
() => import("./lerc-
|
|
209153
|
+
() => import("./lerc-cm5d7rjy.js").then(async (m2) => {
|
|
209149
209154
|
await m2.zstd.init();
|
|
209150
209155
|
return m2;
|
|
209151
209156
|
}).then((m2) => m2.default)
|
|
209152
209157
|
);
|
|
209153
|
-
addDecoder(50001, () => import("./webimage-
|
|
209158
|
+
addDecoder(50001, () => import("./webimage-BjAUnP6y.js").then((m2) => m2.default));
|
|
209154
209159
|
function copyNewSize(array2, width2, height2, samplesPerPixel = 1) {
|
|
209155
209160
|
return new (Object.getPrototypeOf(array2)).constructor(width2 * height2 * samplesPerPixel);
|
|
209156
209161
|
}
|
|
@@ -231309,6 +231314,7 @@ function Legend(props) {
|
|
|
231309
231314
|
positionRelative = false,
|
|
231310
231315
|
highContrast = false,
|
|
231311
231316
|
obsType,
|
|
231317
|
+
isPointsLayer = false,
|
|
231312
231318
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
231313
231319
|
featureType: _featureType = void 0,
|
|
231314
231320
|
// Unused but accepted for API compatibility
|
|
@@ -231316,6 +231322,9 @@ function Legend(props) {
|
|
|
231316
231322
|
considerSelections = true,
|
|
231317
231323
|
obsColorEncoding,
|
|
231318
231324
|
featureSelection,
|
|
231325
|
+
featureFilterMode,
|
|
231326
|
+
featureColor,
|
|
231327
|
+
featureIndex,
|
|
231319
231328
|
featureLabelsMap,
|
|
231320
231329
|
featureValueColormap,
|
|
231321
231330
|
featureValueColormapRange,
|
|
@@ -231359,15 +231368,94 @@ function Legend(props) {
|
|
|
231359
231368
|
debouncedSetRange(rangeValue);
|
|
231360
231369
|
}
|
|
231361
231370
|
}, [debouncedSetRange]);
|
|
231371
|
+
const obsLabel = capitalize$3(obsType ?? null);
|
|
231362
231372
|
const isDarkTheme = theme === "dark";
|
|
231363
|
-
const isStaticColor = obsColorEncoding === "spatialChannelColor" || obsColorEncoding === "spatialLayerColor";
|
|
231364
|
-
const isSetColor = obsColorEncoding === "cellSetSelection";
|
|
231373
|
+
const isStaticColor = !isPointsLayer && (obsColorEncoding === "spatialChannelColor" || obsColorEncoding === "spatialLayerColor");
|
|
231374
|
+
const isSetColor = !isPointsLayer && obsColorEncoding === "cellSetSelection";
|
|
231365
231375
|
const layerColor = Array.isArray(spatialLayerColor) && spatialLayerColor.length === 3 ? spatialLayerColor : getDefaultColor(theme ?? "light");
|
|
231366
231376
|
const channelColor = Array.isArray(spatialChannelColor) && spatialChannelColor.length === 3 ? spatialChannelColor : getDefaultColor(theme ?? "light");
|
|
231367
231377
|
const staticColor = obsColorEncoding === "spatialChannelColor" ? channelColor : layerColor;
|
|
231368
|
-
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);
|
|
231378
|
+
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);
|
|
231379
|
+
const pointsLegendElements = [];
|
|
231380
|
+
if (isPointsLayer) {
|
|
231381
|
+
const MAX_NUM_COLORS = 10;
|
|
231382
|
+
const hasFeatureSelection = Array.isArray(featureSelection) && featureSelection.length > 0;
|
|
231383
|
+
const showUnselected = featureFilterMode !== "featureSelection";
|
|
231384
|
+
if (obsColorEncoding === "spatialLayerColor") {
|
|
231385
|
+
if (!hasFeatureSelection) {
|
|
231386
|
+
pointsLegendElements.push({
|
|
231387
|
+
name: obsLabel,
|
|
231388
|
+
color: staticColor
|
|
231389
|
+
});
|
|
231390
|
+
} else {
|
|
231391
|
+
const limitedFeatureSelection = featureSelection.slice(0, MAX_NUM_COLORS);
|
|
231392
|
+
limitedFeatureSelection.forEach((featureName) => {
|
|
231393
|
+
pointsLegendElements.push({
|
|
231394
|
+
name: featureName,
|
|
231395
|
+
color: staticColor
|
|
231396
|
+
});
|
|
231397
|
+
});
|
|
231398
|
+
}
|
|
231399
|
+
} else if (obsColorEncoding === "geneSelection") {
|
|
231400
|
+
if (!hasFeatureSelection) {
|
|
231401
|
+
pointsLegendElements.push({
|
|
231402
|
+
name: obsLabel,
|
|
231403
|
+
color: staticColor
|
|
231404
|
+
});
|
|
231405
|
+
} else {
|
|
231406
|
+
const limitedFeatureSelection = featureSelection.slice(0, MAX_NUM_COLORS);
|
|
231407
|
+
limitedFeatureSelection.forEach((featureName) => {
|
|
231408
|
+
const featureColorMatch = Array.isArray(featureColor) ? featureColor.find((fc) => fc.name === featureName)?.color : null;
|
|
231409
|
+
pointsLegendElements.push({
|
|
231410
|
+
name: featureName,
|
|
231411
|
+
// If no color is specified for this feature, use staticColor.
|
|
231412
|
+
color: featureColorMatch ?? staticColor
|
|
231413
|
+
});
|
|
231414
|
+
});
|
|
231415
|
+
}
|
|
231416
|
+
} else if (obsColorEncoding === "randomByFeature") {
|
|
231417
|
+
if (!hasFeatureSelection) {
|
|
231418
|
+
pointsLegendElements.push({
|
|
231419
|
+
name: obsLabel,
|
|
231420
|
+
// For now, using black and white for this.
|
|
231421
|
+
// (It should not match any color in PALETTE)
|
|
231422
|
+
color: isDarkTheme ? [255, 255, 255] : [0, 0, 0]
|
|
231423
|
+
});
|
|
231424
|
+
} else {
|
|
231425
|
+
const limitedFeatureSelection = featureSelection.slice(0, MAX_NUM_COLORS);
|
|
231426
|
+
limitedFeatureSelection.forEach((featureName) => {
|
|
231427
|
+
const varIndex = (featureIndex ?? []).indexOf(featureName);
|
|
231428
|
+
const featureColorMatch = varIndex >= 0 ? PALETTE[varIndex % PALETTE.length] : null;
|
|
231429
|
+
pointsLegendElements.push({
|
|
231430
|
+
name: featureName,
|
|
231431
|
+
// If no color is specified for this feature, use staticColor.
|
|
231432
|
+
color: featureColorMatch ?? staticColor
|
|
231433
|
+
});
|
|
231434
|
+
});
|
|
231435
|
+
}
|
|
231436
|
+
} else if (obsColorEncoding === "random") {
|
|
231437
|
+
pointsLegendElements.push({
|
|
231438
|
+
name: obsLabel,
|
|
231439
|
+
// For now, using black and white for this.
|
|
231440
|
+
// (It should not match any color in PALETTE)
|
|
231441
|
+
color: isDarkTheme ? [255, 255, 255] : [0, 0, 0]
|
|
231442
|
+
});
|
|
231443
|
+
}
|
|
231444
|
+
if (showUnselected) {
|
|
231445
|
+
pointsLegendElements.push({
|
|
231446
|
+
name: "Unselected",
|
|
231447
|
+
color: getDefaultColor(theme ?? "light")
|
|
231448
|
+
});
|
|
231449
|
+
}
|
|
231450
|
+
}
|
|
231369
231451
|
const levelZeroNames = useMemo$1(() => Array.from(new Set(obsSetSelection?.map((setPath) => setPath[0]) || [])), [obsSetSelection]);
|
|
231370
|
-
const dynamicHeight =
|
|
231452
|
+
const dynamicHeight = isPointsLayer ? (
|
|
231453
|
+
// Height logic for points layers.
|
|
231454
|
+
pointsLegendElements.length * (rectHeight + rectMarginY) + titleHeight
|
|
231455
|
+
) : (
|
|
231456
|
+
// Height logic for non-points layers.
|
|
231457
|
+
isSetColor && obsSetSelection ? levelZeroNames.length * titleHeight + (obsSetSelection?.length ?? 0) * (rectHeight + rectMarginY) : height2 + (!pointsVisible && contoursVisible ? 25 : 0)
|
|
231458
|
+
);
|
|
231371
231459
|
const availHeight = maxHeight2 !== null ? Math.max(0, maxHeight2 - 4) : Infinity;
|
|
231372
231460
|
const needsScroll = Number.isFinite(availHeight) && dynamicHeight > availHeight + 1;
|
|
231373
231461
|
useEffect(() => {
|
|
@@ -231379,8 +231467,8 @@ function Legend(props) {
|
|
|
231379
231467
|
svg2.selectAll("g").remove();
|
|
231380
231468
|
svg2.attr("width", width2).attr("height", dynamicHeight);
|
|
231381
231469
|
const g2 = svg2.append("g").attr("width", width2).attr("height", dynamicHeight);
|
|
231382
|
-
const showInteractiveSlider2 = setFeatureValueColormapRange && ["geneSelection", "geneExpression"].includes(obsColorEncoding ?? "") && pointsVisible && featureValueColormap;
|
|
231383
|
-
if (!considerSelections || ["geneSelection", "geneExpression"].includes(obsColorEncoding ?? "")) {
|
|
231470
|
+
const showInteractiveSlider2 = !isPointsLayer && setFeatureValueColormapRange && ["geneSelection", "geneExpression"].includes(obsColorEncoding ?? "") && pointsVisible && featureValueColormap;
|
|
231471
|
+
if (!isPointsLayer && (!considerSelections || ["geneSelection", "geneExpression"].includes(obsColorEncoding ?? ""))) {
|
|
231384
231472
|
const combinedExtent = combineExtents(extent2 ?? null, featureAggregationStrategy ?? null) || [0, 1];
|
|
231385
231473
|
const [xMin, xMax] = combinedExtent;
|
|
231386
231474
|
if (featureValueColormap && pointsVisible) {
|
|
@@ -231440,10 +231528,10 @@ function Legend(props) {
|
|
|
231440
231528
|
});
|
|
231441
231529
|
}
|
|
231442
231530
|
}
|
|
231443
|
-
if (isStaticColor) {
|
|
231531
|
+
if (!isPointsLayer && isStaticColor) {
|
|
231444
231532
|
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]})`);
|
|
231445
231533
|
}
|
|
231446
|
-
if (isSetColor && obsSetSelection && obsSetColor) {
|
|
231534
|
+
if (!isPointsLayer && isSetColor && obsSetSelection && obsSetColor) {
|
|
231447
231535
|
const obsSetSelectionByLevelZero = {};
|
|
231448
231536
|
obsSetSelection.forEach((setPath) => {
|
|
231449
231537
|
const levelZeroName = setPath[0];
|
|
@@ -231464,6 +231552,16 @@ function Legend(props) {
|
|
|
231464
231552
|
});
|
|
231465
231553
|
});
|
|
231466
231554
|
}
|
|
231555
|
+
if (isPointsLayer) {
|
|
231556
|
+
let y2 = 0;
|
|
231557
|
+
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);
|
|
231558
|
+
y2 += titleHeight;
|
|
231559
|
+
pointsLegendElements.forEach(({ name: name2, color: color2 }) => {
|
|
231560
|
+
g2.append("rect").attr("x", 0).attr("y", y2).attr("width", rectHeight).attr("height", rectHeight).attr("fill", `rgb(${color2[0]},${color2[1]},${color2[2]})`);
|
|
231561
|
+
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);
|
|
231562
|
+
y2 += rectHeight + rectMarginY;
|
|
231563
|
+
});
|
|
231564
|
+
}
|
|
231467
231565
|
const featureSelectionLabelRaw = featureSelection && featureSelection.length >= 1 && !isStaticColor ? featureSelection.map((geneName) => featureLabelsMap?.get(geneName) || featureLabelsMap?.get(cleanFeatureId(geneName)) || geneName) : null;
|
|
231468
231566
|
let featureSelectionLabelRawStr = "";
|
|
231469
231567
|
if (featureAggregationStrategy === "first") {
|
|
@@ -231490,12 +231588,11 @@ function Legend(props) {
|
|
|
231490
231588
|
}
|
|
231491
231589
|
const combinedMissing = combineMissings(missing ?? null, featureAggregationStrategy ?? null);
|
|
231492
231590
|
const featureSelectionLabel = combinedMissing ? `${featureSelectionLabelRawStr} (${Math.round(combinedMissing * 100)}% NaN)` : featureSelectionLabelRawStr;
|
|
231493
|
-
const obsLabel = capitalize$3(obsType ?? null);
|
|
231494
231591
|
const featureLabel = considerSelections ? featureSelectionLabel || capitalize$3(featureValueType ?? null) : capitalize$3(featureValueType ?? null);
|
|
231495
231592
|
const mainLabel = showObsLabel ? obsLabel : featureLabel;
|
|
231496
231593
|
const subLabel = showObsLabel ? featureLabel : null;
|
|
231497
231594
|
const hasSubLabel = subLabel !== null;
|
|
231498
|
-
if (!isSetColor) {
|
|
231595
|
+
if (!isPointsLayer && !isSetColor) {
|
|
231499
231596
|
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);
|
|
231500
231597
|
if (hasSubLabel) {
|
|
231501
231598
|
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);
|
|
@@ -231534,7 +231631,7 @@ function Legend(props) {
|
|
|
231534
231631
|
showObsLabel,
|
|
231535
231632
|
staticColor
|
|
231536
231633
|
]);
|
|
231537
|
-
const showInteractiveSlider = setFeatureValueColormapRange && ["geneSelection", "geneExpression"].includes(obsColorEncoding ?? "") && pointsVisible && featureValueColormap;
|
|
231634
|
+
const showInteractiveSlider = !isPointsLayer && setFeatureValueColormapRange && ["geneSelection", "geneExpression"].includes(obsColorEncoding ?? "") && pointsVisible && featureValueColormap;
|
|
231538
231635
|
const globalExtent = useMemo$1(() => {
|
|
231539
231636
|
const combined = combineExtents(extent2 ?? null, featureAggregationStrategy ?? null);
|
|
231540
231637
|
return combined || [0, 1];
|
|
@@ -231607,7 +231704,8 @@ function MultiLegend(props) {
|
|
|
231607
231704
|
spotMultiFeatureLabels,
|
|
231608
231705
|
// Points
|
|
231609
231706
|
pointLayerScopes,
|
|
231610
|
-
pointLayerCoordination
|
|
231707
|
+
pointLayerCoordination,
|
|
231708
|
+
pointMultiIndicesData
|
|
231611
231709
|
} = props;
|
|
231612
231710
|
const { classes: classes2 } = useStyles$o();
|
|
231613
231711
|
const reversedSegmentationLayerScopes = useMemo$1(() => [...segmentationLayerScopes || []].reverse(), [segmentationLayerScopes]);
|
|
@@ -231618,7 +231716,8 @@ function MultiLegend(props) {
|
|
|
231618
231716
|
const layerSetters = pointLayerCoordination?.[1]?.[layerScope];
|
|
231619
231717
|
if (!layerCoordination)
|
|
231620
231718
|
return null;
|
|
231621
|
-
const { spatialLayerVisible, obsColorEncoding, obsType, featureType, featureValueType, featureSelection, featureValueColormap, featureValueColormapRange, spatialLayerColor, legendVisible } = layerCoordination;
|
|
231719
|
+
const { spatialLayerVisible, obsColorEncoding, obsType, featureType, featureValueType, featureSelection, featureColor, featureFilterMode, featureValueColormap, featureValueColormapRange, spatialLayerColor, legendVisible } = layerCoordination;
|
|
231720
|
+
const pointIndicesData = pointMultiIndicesData?.[layerScope];
|
|
231622
231721
|
const { setFeatureValueColormapRange } = layerSetters || {};
|
|
231623
231722
|
const isStaticColor = obsColorEncoding === "spatialLayerColor";
|
|
231624
231723
|
const height2 = isStaticColor ? 20 : 36;
|
|
@@ -231635,6 +231734,10 @@ function MultiLegend(props) {
|
|
|
231635
231734
|
obsColorEncoding,
|
|
231636
231735
|
spatialLayerColor,
|
|
231637
231736
|
featureSelection,
|
|
231737
|
+
featureFilterMode,
|
|
231738
|
+
featureColor,
|
|
231739
|
+
featureIndex: pointIndicesData?.featureIndex,
|
|
231740
|
+
isPointsLayer: true,
|
|
231638
231741
|
// featureLabelsMap={featureLabelsMap} // TODO
|
|
231639
231742
|
featureValueColormap: featureValueColormap || "viridis",
|
|
231640
231743
|
featureValueColormapRange: featureValueColormapRange || [0, 1],
|
|
@@ -252046,6 +252149,7 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
|
|
|
252046
252149
|
this.obsSpotsQuadTree = {};
|
|
252047
252150
|
this.obsPointsData = {};
|
|
252048
252151
|
this.obsPointsQuadTree = {};
|
|
252152
|
+
this.obsPointsLoadingStatus = {};
|
|
252049
252153
|
this.imageLayers = [];
|
|
252050
252154
|
this.obsSegmentationsLayers = [];
|
|
252051
252155
|
this.obsSpotsLayers = [];
|
|
@@ -252226,10 +252330,131 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
|
|
|
252226
252330
|
});
|
|
252227
252331
|
}
|
|
252228
252332
|
createPointLayer(layerScope, layerCoordination, layerObsPoints) {
|
|
252229
|
-
const { theme, delegateHover, targetZ } = this.props;
|
|
252230
|
-
const { spatialLayerVisible, spatialLayerOpacity, obsColorEncoding, spatialLayerColor } = layerCoordination;
|
|
252231
|
-
const
|
|
252333
|
+
const { theme, delegateHover, targetZ, pointMatrixIndices, setTiledPointsLoadingProgress } = this.props;
|
|
252334
|
+
const { spatialLayerVisible, spatialLayerOpacity, obsColorEncoding, spatialLayerColor, featureSelection, featureFilterMode, featureColor } = layerCoordination;
|
|
252335
|
+
const pointFeatureIndex = pointMatrixIndices?.[layerScope]?.featureIndex;
|
|
252336
|
+
let featureIndices = [];
|
|
252337
|
+
if (Array.isArray(featureSelection) && featureSelection.length >= 1) {
|
|
252338
|
+
if (pointFeatureIndex) {
|
|
252339
|
+
featureIndices = featureSelection.map((geneName) => pointFeatureIndex.indexOf(geneName)).filter((i2) => i2 >= 0);
|
|
252340
|
+
}
|
|
252341
|
+
}
|
|
252232
252342
|
const staticColor = Array.isArray(spatialLayerColor) && spatialLayerColor.length === 3 ? spatialLayerColor : getDefaultColor(theme);
|
|
252343
|
+
const defaultColor = getDefaultColor(theme);
|
|
252344
|
+
let getFillColor = null;
|
|
252345
|
+
const hasFeatureSelection = Array.isArray(featureSelection) && featureSelection.length > 0;
|
|
252346
|
+
const showUnselected = featureFilterMode !== "featureSelection";
|
|
252347
|
+
const hasMultipleFeaturesSelected = Array.isArray(featureIndices) && featureIndices.length > 1;
|
|
252348
|
+
if (obsColorEncoding === "spatialLayerColor") {
|
|
252349
|
+
getFillColor = (object2, { index: index2, data: data2, target: target2 }) => {
|
|
252350
|
+
if (!hasFeatureSelection || featureIndices.includes(data2.src.featureIndices[index2])) {
|
|
252351
|
+
target2[0] = staticColor[0];
|
|
252352
|
+
target2[1] = staticColor[1];
|
|
252353
|
+
target2[2] = staticColor[2];
|
|
252354
|
+
target2[3] = 255;
|
|
252355
|
+
return target2;
|
|
252356
|
+
}
|
|
252357
|
+
if (!showUnselected) {
|
|
252358
|
+
if (hasMultipleFeaturesSelected) {
|
|
252359
|
+
target2[3] = 0;
|
|
252360
|
+
}
|
|
252361
|
+
return target2;
|
|
252362
|
+
}
|
|
252363
|
+
target2[0] = defaultColor[0];
|
|
252364
|
+
target2[1] = defaultColor[1];
|
|
252365
|
+
target2[2] = defaultColor[2];
|
|
252366
|
+
target2[3] = 255;
|
|
252367
|
+
return target2;
|
|
252368
|
+
};
|
|
252369
|
+
} else if (obsColorEncoding === "geneSelection") {
|
|
252370
|
+
getFillColor = (object2, { index: index2, data: data2, target: target2 }) => {
|
|
252371
|
+
if (!hasFeatureSelection) {
|
|
252372
|
+
target2[0] = staticColor[0];
|
|
252373
|
+
target2[1] = staticColor[1];
|
|
252374
|
+
target2[2] = staticColor[2];
|
|
252375
|
+
target2[3] = 255;
|
|
252376
|
+
return target2;
|
|
252377
|
+
}
|
|
252378
|
+
const isSelected = featureIndices.includes(data2.src.featureIndices[index2]);
|
|
252379
|
+
if (isSelected) {
|
|
252380
|
+
const featureName = pointFeatureIndex?.[data2.src.featureIndices[index2]];
|
|
252381
|
+
const featureColorMatch = Array.isArray(featureColor) ? featureColor.find((fc) => fc.name === featureName)?.color : null;
|
|
252382
|
+
if (featureColorMatch) {
|
|
252383
|
+
target2[0] = featureColorMatch[0];
|
|
252384
|
+
target2[1] = featureColorMatch[1];
|
|
252385
|
+
target2[2] = featureColorMatch[2];
|
|
252386
|
+
target2[3] = 255;
|
|
252387
|
+
return target2;
|
|
252388
|
+
}
|
|
252389
|
+
target2[0] = staticColor[0];
|
|
252390
|
+
target2[1] = staticColor[1];
|
|
252391
|
+
target2[2] = staticColor[2];
|
|
252392
|
+
target2[3] = 255;
|
|
252393
|
+
return target2;
|
|
252394
|
+
}
|
|
252395
|
+
if (!showUnselected) {
|
|
252396
|
+
if (hasMultipleFeaturesSelected) {
|
|
252397
|
+
target2[3] = 0;
|
|
252398
|
+
}
|
|
252399
|
+
return target2;
|
|
252400
|
+
}
|
|
252401
|
+
target2[0] = defaultColor[0];
|
|
252402
|
+
target2[1] = defaultColor[1];
|
|
252403
|
+
target2[2] = defaultColor[2];
|
|
252404
|
+
target2[3] = 255;
|
|
252405
|
+
return target2;
|
|
252406
|
+
};
|
|
252407
|
+
} else if (obsColorEncoding === "randomByFeature") {
|
|
252408
|
+
{
|
|
252409
|
+
getFillColor = (object2, { index: index2, data: data2, target: target2 }) => {
|
|
252410
|
+
if (!hasFeatureSelection || featureIndices.includes(data2.src.featureIndices[index2])) {
|
|
252411
|
+
const varIndex = data2.src.featureIndices[index2];
|
|
252412
|
+
const color2 = PALETTE[varIndex % PALETTE.length];
|
|
252413
|
+
target2[0] = color2[0];
|
|
252414
|
+
target2[1] = color2[1];
|
|
252415
|
+
target2[2] = color2[2];
|
|
252416
|
+
target2[3] = 255;
|
|
252417
|
+
return target2;
|
|
252418
|
+
}
|
|
252419
|
+
if (!showUnselected) {
|
|
252420
|
+
if (hasMultipleFeaturesSelected) {
|
|
252421
|
+
target2[3] = 0;
|
|
252422
|
+
}
|
|
252423
|
+
return target2;
|
|
252424
|
+
}
|
|
252425
|
+
target2[0] = defaultColor[0];
|
|
252426
|
+
target2[1] = defaultColor[1];
|
|
252427
|
+
target2[2] = defaultColor[2];
|
|
252428
|
+
target2[3] = 255;
|
|
252429
|
+
return target2;
|
|
252430
|
+
};
|
|
252431
|
+
}
|
|
252432
|
+
} else if (obsColorEncoding === "random") {
|
|
252433
|
+
{
|
|
252434
|
+
getFillColor = (object2, { index: index2, data: data2, target: target2 }) => {
|
|
252435
|
+
if (!hasFeatureSelection || featureIndices.includes(data2.src.featureIndices[index2])) {
|
|
252436
|
+
const color2 = PALETTE[index2 % PALETTE.length];
|
|
252437
|
+
target2[0] = color2[0];
|
|
252438
|
+
target2[1] = color2[1];
|
|
252439
|
+
target2[2] = color2[2];
|
|
252440
|
+
target2[3] = 255;
|
|
252441
|
+
return target2;
|
|
252442
|
+
}
|
|
252443
|
+
if (!showUnselected) {
|
|
252444
|
+
if (hasMultipleFeaturesSelected) {
|
|
252445
|
+
target2[3] = 0;
|
|
252446
|
+
}
|
|
252447
|
+
return target2;
|
|
252448
|
+
}
|
|
252449
|
+
target2[0] = defaultColor[0];
|
|
252450
|
+
target2[1] = defaultColor[1];
|
|
252451
|
+
target2[2] = defaultColor[2];
|
|
252452
|
+
target2[3] = 255;
|
|
252453
|
+
return target2;
|
|
252454
|
+
};
|
|
252455
|
+
}
|
|
252456
|
+
}
|
|
252457
|
+
const isStaticColor = obsColorEncoding === "spatialLayerColor";
|
|
252233
252458
|
const getMoleculeColor = (object2, { data: data2, index: index2, target: target2 }) => {
|
|
252234
252459
|
const obsId = data2.src.obsIndex[index2];
|
|
252235
252460
|
if (data2.src.obsLabelsMap && data2.src.uniqueObsLabels && data2.src.PALETTE) {
|
|
@@ -252241,11 +252466,131 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
|
|
|
252241
252466
|
}
|
|
252242
252467
|
return target2;
|
|
252243
252468
|
};
|
|
252244
|
-
const { obsPointsModelMatrix, obsPoints } = this.obsPointsData?.[layerScope]?.src ?? {};
|
|
252245
|
-
|
|
252469
|
+
const { obsPointsModelMatrix, obsPoints, obsPointsTilingType, loadPointsInRect } = this.obsPointsData?.[layerScope]?.src ?? {};
|
|
252470
|
+
obsPoints?.shape?.[0] === 3;
|
|
252246
252471
|
const modelMatrix2 = obsPointsModelMatrix?.clone();
|
|
252247
|
-
if (
|
|
252248
|
-
|
|
252472
|
+
if (obsPointsTilingType === "tiled") {
|
|
252473
|
+
return new TileLayer({
|
|
252474
|
+
id: `Tiled-${POINT_LAYER_PREFIX}${layerScope}`,
|
|
252475
|
+
coordinateSystem: COORDINATE_SYSTEM.CARTESIAN,
|
|
252476
|
+
// NOTE: picking is not working due to https://github.com/vitessce/vitessce/issues/2039
|
|
252477
|
+
modelMatrix: modelMatrix2,
|
|
252478
|
+
pickable: true,
|
|
252479
|
+
autoHighlight: true,
|
|
252480
|
+
onHover: (info2) => delegateHover(info2, "point", layerScope),
|
|
252481
|
+
opacity: spatialLayerOpacity,
|
|
252482
|
+
visible: spatialLayerVisible,
|
|
252483
|
+
// Since points are tiled but not multi-resolution,
|
|
252484
|
+
// it provides no benefit to request tiles at different zoom levels.
|
|
252485
|
+
// TODO: Should this value be the same for
|
|
252486
|
+
// every dataset, or do we need to
|
|
252487
|
+
// adjust based on the extent/density of the
|
|
252488
|
+
// point data (and/or account for modelMatrix, etc)?
|
|
252489
|
+
maxZoom: -1,
|
|
252490
|
+
minZoom: -1,
|
|
252491
|
+
tileSize: 512,
|
|
252492
|
+
// refinementStrategy: 'no-overlap',
|
|
252493
|
+
getTileData: async (tileInfo) => {
|
|
252494
|
+
const { index: index2, signal, bbox: bbox2, zoom: zoom2 } = tileInfo;
|
|
252495
|
+
const { z: z2, x: x2, y: y2 } = index2;
|
|
252496
|
+
this.obsPointsLoadingStatus = {
|
|
252497
|
+
...this.obsPointsLoadingStatus,
|
|
252498
|
+
[`${layerScope}-${z2}-${x2}-${y2}`]: "loading"
|
|
252499
|
+
};
|
|
252500
|
+
setTiledPointsLoadingProgress(this.obsPointsLoadingStatus);
|
|
252501
|
+
signal.addEventListener("abort", () => {
|
|
252502
|
+
this.obsPointsLoadingStatus = {
|
|
252503
|
+
...this.obsPointsLoadingStatus,
|
|
252504
|
+
[`${layerScope}-${z2}-${x2}-${y2}`]: "aborted"
|
|
252505
|
+
};
|
|
252506
|
+
setTiledPointsLoadingProgress(this.obsPointsLoadingStatus);
|
|
252507
|
+
});
|
|
252508
|
+
const pointsInTile = await loadPointsInRect(bbox2, signal);
|
|
252509
|
+
this.obsPointsLoadingStatus = {
|
|
252510
|
+
...this.obsPointsLoadingStatus,
|
|
252511
|
+
[`${layerScope}-${z2}-${x2}-${y2}`]: "success"
|
|
252512
|
+
};
|
|
252513
|
+
setTiledPointsLoadingProgress(this.obsPointsLoadingStatus);
|
|
252514
|
+
return {
|
|
252515
|
+
src: pointsInTile.data,
|
|
252516
|
+
length: pointsInTile.shape?.[1] || 0
|
|
252517
|
+
};
|
|
252518
|
+
},
|
|
252519
|
+
renderSubLayers: (subLayerProps) => {
|
|
252520
|
+
const { bbox: bbox2, content: tileData } = subLayerProps.tile;
|
|
252521
|
+
const { left: left2, top: top2, right: right2, bottom: bottom2 } = bbox2;
|
|
252522
|
+
const hasFeatureIndicesMinMax = !showUnselected && Array.isArray(featureIndices) && featureIndices.length === 1;
|
|
252523
|
+
const FILTER_PLACEHOLDER = 0;
|
|
252524
|
+
const featureIndicesMinMax = hasFeatureIndicesMinMax ? [featureIndices[0], featureIndices[0]] : [FILTER_PLACEHOLDER, FILTER_PLACEHOLDER];
|
|
252525
|
+
return new ScatterplotLayer(subLayerProps, {
|
|
252526
|
+
bounds: [left2, top2, right2, bottom2],
|
|
252527
|
+
data: tileData,
|
|
252528
|
+
getRadius: 5,
|
|
252529
|
+
radiusMaxPixels: 3,
|
|
252530
|
+
// getPosition: d => d,
|
|
252531
|
+
// getFillColor: [255, 0, 0],
|
|
252532
|
+
getPosition: (object2, { data: data2, index: index2, target: target2 }) => {
|
|
252533
|
+
target2[0] = data2.src.x[index2];
|
|
252534
|
+
target2[1] = data2.src.y[index2];
|
|
252535
|
+
target2[2] = 0;
|
|
252536
|
+
return target2;
|
|
252537
|
+
},
|
|
252538
|
+
getFillColor,
|
|
252539
|
+
// TODO: Is the picking stuff needed here in the Sublayer, or in the parent TileLayer?
|
|
252540
|
+
pickable: true,
|
|
252541
|
+
autoHighlight: true,
|
|
252542
|
+
onHover: (info2) => delegateHover(info2, "point", layerScope),
|
|
252543
|
+
// Use GPU filtering to filter to only the points in the tile bounding box,
|
|
252544
|
+
// since the row groups may contain points from other tiles.
|
|
252545
|
+
// Note: this can be improved using filterCategories,
|
|
252546
|
+
// but it is not available until post-v9 deck.gl/extensions.
|
|
252547
|
+
filterRange: [[left2, right2], [top2, bottom2], featureIndicesMinMax],
|
|
252548
|
+
getFilterValue: hasFeatureIndicesMinMax ? (object2, { data: data2, index: index2 }) => [
|
|
252549
|
+
data2.src.x[index2],
|
|
252550
|
+
data2.src.y[index2],
|
|
252551
|
+
data2.src.featureIndices[index2]
|
|
252552
|
+
] : (object2, { data: data2, index: index2 }) => [
|
|
252553
|
+
data2.src.x[index2],
|
|
252554
|
+
data2.src.y[index2],
|
|
252555
|
+
FILTER_PLACEHOLDER
|
|
252556
|
+
],
|
|
252557
|
+
extensions: [
|
|
252558
|
+
new DataFilterExtension({ filterSize: 3 })
|
|
252559
|
+
],
|
|
252560
|
+
updateTriggers: {
|
|
252561
|
+
getFillColor: [
|
|
252562
|
+
showUnselected,
|
|
252563
|
+
featureColor,
|
|
252564
|
+
obsColorEncoding,
|
|
252565
|
+
spatialLayerColor,
|
|
252566
|
+
featureSelection,
|
|
252567
|
+
hasMultipleFeaturesSelected
|
|
252568
|
+
],
|
|
252569
|
+
getFilterValue: [hasFeatureIndicesMinMax, showUnselected, featureSelection],
|
|
252570
|
+
filterRange: [hasFeatureIndicesMinMax, showUnselected, featureSelection]
|
|
252571
|
+
}
|
|
252572
|
+
});
|
|
252573
|
+
},
|
|
252574
|
+
updateTriggers: {
|
|
252575
|
+
getTileData: [
|
|
252576
|
+
showUnselected,
|
|
252577
|
+
featureColor,
|
|
252578
|
+
obsColorEncoding,
|
|
252579
|
+
spatialLayerColor,
|
|
252580
|
+
featureSelection,
|
|
252581
|
+
hasMultipleFeaturesSelected
|
|
252582
|
+
]
|
|
252583
|
+
}
|
|
252584
|
+
/*
|
|
252585
|
+
onTileError: (error) => {
|
|
252586
|
+
|
|
252587
|
+
},
|
|
252588
|
+
onViewportLoad: (loadedTiles) => {
|
|
252589
|
+
// Called when all tiles in the current viewport are loaded.
|
|
252590
|
+
// An array of loaded Tile instances are passed as argument to this function.
|
|
252591
|
+
},
|
|
252592
|
+
*/
|
|
252593
|
+
});
|
|
252249
252594
|
}
|
|
252250
252595
|
return new ScatterplotLayer({
|
|
252251
252596
|
id: `${POINT_LAYER_PREFIX}${layerScope}`,
|
|
@@ -252272,16 +252617,7 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
|
|
|
252272
252617
|
getFillColor: [obsColorEncoding, staticColor],
|
|
252273
252618
|
getLineColor: [obsColorEncoding, staticColor]
|
|
252274
252619
|
},
|
|
252275
|
-
...
|
|
252276
|
-
// TODO: support targetT filtering as well.
|
|
252277
|
-
// TODO: allow filtering by Z coordinate (rather than slice index)
|
|
252278
|
-
// Reference: https://github.com/vitessce/vitessce/issues/2194
|
|
252279
|
-
filterRange: [targetZ, targetZ],
|
|
252280
|
-
getFilterValue: (object2, { data: data2, index: index2 }) => data2.src.obsPoints.data[2][index2],
|
|
252281
|
-
extensions: [
|
|
252282
|
-
new DataFilterExtension({ filterSize: 1 })
|
|
252283
|
-
]
|
|
252284
|
-
} : {}
|
|
252620
|
+
...{}
|
|
252285
252621
|
});
|
|
252286
252622
|
}
|
|
252287
252623
|
createSelectionLayer() {
|
|
@@ -252821,28 +253157,45 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
|
|
|
252821
253157
|
}
|
|
252822
253158
|
onUpdatePointsData(layerScope) {
|
|
252823
253159
|
const { obsPoints, pointMultiObsLabels } = this.props;
|
|
252824
|
-
const { obsIndex, obsPoints: layerObsPoints, obsPointsModelMatrix } = obsPoints?.[layerScope] || {};
|
|
253160
|
+
const { obsIndex, obsPoints: layerObsPoints, obsPointsModelMatrix, loadPointsInRect, obsPointsTilingType } = obsPoints?.[layerScope] || {};
|
|
252825
253161
|
const { obsIndex: obsLabelsIndex, obsLabels } = pointMultiObsLabels?.[layerScope] || {};
|
|
252826
|
-
if (
|
|
252827
|
-
const getCellCoords = makeDefaultGetObsCoords(layerObsPoints);
|
|
252828
|
-
this.obsPointsQuadTree[layerScope] = createQuadTree(layerObsPoints, getCellCoords);
|
|
253162
|
+
if (obsPointsTilingType === "tiled") {
|
|
252829
253163
|
this.obsPointsData[layerScope] = {
|
|
252830
253164
|
src: {
|
|
252831
|
-
|
|
252832
|
-
|
|
253165
|
+
obsPointsTilingType,
|
|
253166
|
+
obsIndex: null,
|
|
253167
|
+
obsPoints: null,
|
|
252833
253168
|
obsPointsModelMatrix,
|
|
252834
253169
|
obsLabelsMap: null,
|
|
252835
253170
|
uniqueObsLabels: null,
|
|
252836
|
-
PALETTE: null
|
|
253171
|
+
PALETTE: null,
|
|
253172
|
+
loadPointsInRect
|
|
252837
253173
|
},
|
|
252838
|
-
length:
|
|
253174
|
+
length: null
|
|
252839
253175
|
};
|
|
252840
|
-
|
|
252841
|
-
|
|
252842
|
-
const
|
|
252843
|
-
this.
|
|
252844
|
-
this.obsPointsData[layerScope]
|
|
252845
|
-
|
|
253176
|
+
} else {
|
|
253177
|
+
if (layerObsPoints) {
|
|
253178
|
+
const getCellCoords = makeDefaultGetObsCoords(layerObsPoints);
|
|
253179
|
+
this.obsPointsQuadTree[layerScope] = createQuadTree(layerObsPoints, getCellCoords);
|
|
253180
|
+
this.obsPointsData[layerScope] = {
|
|
253181
|
+
src: {
|
|
253182
|
+
obsPointsTilingType,
|
|
253183
|
+
obsIndex,
|
|
253184
|
+
obsPoints: layerObsPoints,
|
|
253185
|
+
obsPointsModelMatrix,
|
|
253186
|
+
obsLabelsMap: null,
|
|
253187
|
+
uniqueObsLabels: null,
|
|
253188
|
+
PALETTE: null
|
|
253189
|
+
},
|
|
253190
|
+
length: layerObsPoints.shape[1]
|
|
253191
|
+
};
|
|
253192
|
+
if (obsLabels) {
|
|
253193
|
+
const obsLabelsMap = new Map(obsLabelsIndex.map((key2, i2) => [key2, obsLabels[i2]]));
|
|
253194
|
+
const uniqueObsLabels = Array.from(new Set(obsLabels));
|
|
253195
|
+
this.obsPointsData[layerScope].src.obsLabelsMap = obsLabelsMap;
|
|
253196
|
+
this.obsPointsData[layerScope].src.uniqueObsLabels = uniqueObsLabels;
|
|
253197
|
+
this.obsPointsData[layerScope].src.PALETTE = PALETTE;
|
|
253198
|
+
}
|
|
252846
253199
|
}
|
|
252847
253200
|
}
|
|
252848
253201
|
}
|
|
@@ -253051,6 +253404,7 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
|
|
|
253051
253404
|
// Data props.
|
|
253052
253405
|
"obsPoints",
|
|
253053
253406
|
"pointMultiObsLabels",
|
|
253407
|
+
"pointMatrixIndices",
|
|
253054
253408
|
// Coordination props.
|
|
253055
253409
|
"pointLayerScopes",
|
|
253056
253410
|
"pointLayerCoordination"
|
|
@@ -253205,12 +253559,12 @@ class ErrorBoundary extends React__default.Component {
|
|
|
253205
253559
|
}
|
|
253206
253560
|
}
|
|
253207
253561
|
const LazySpatialThree = React__default.lazy(async () => {
|
|
253208
|
-
const { SpatialWrapper: SpatialWrapper2 } = await import("./index-
|
|
253562
|
+
const { SpatialWrapper: SpatialWrapper2 } = await import("./index-SH4i0VjQ.js");
|
|
253209
253563
|
return { default: SpatialWrapper2 };
|
|
253210
253564
|
});
|
|
253211
253565
|
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 }) }) }) }));
|
|
253212
253566
|
const LazySpatialAccelerated = React__default.lazy(async () => {
|
|
253213
|
-
const { SpatialWrapper: SpatialWrapper2 } = await import("./index-
|
|
253567
|
+
const { SpatialWrapper: SpatialWrapper2 } = await import("./index-gdPd0Ws9.js");
|
|
253214
253568
|
return { default: SpatialWrapper2 };
|
|
253215
253569
|
});
|
|
253216
253570
|
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 }) }) }) }));
|
|
@@ -253325,12 +253679,22 @@ const DEFAULT_VIEW_STATE = {
|
|
|
253325
253679
|
const SET_VIEW_STATE_NOOP = () => {
|
|
253326
253680
|
};
|
|
253327
253681
|
function getHoverData(hoverInfo, layerType) {
|
|
253328
|
-
const { coordinate, sourceLayer: layer, tile } = hoverInfo;
|
|
253329
|
-
if (layerType === "segmentation-bitmask" || layerType === "image") {
|
|
253682
|
+
const { coordinate, sourceLayer: layer, tile, index: pointIndex } = hoverInfo;
|
|
253683
|
+
if (layerType === "segmentation-bitmask" || layerType === "image" || layerType === "point") {
|
|
253330
253684
|
if (coordinate && layer) {
|
|
253331
253685
|
if (layer.id.startsWith("Tiled") && tile) {
|
|
253332
253686
|
const { content: content2, bbox: bbox2, index: { z: z2 } } = tile;
|
|
253333
253687
|
if (content2) {
|
|
253688
|
+
if (layerType === "point" && pointIndex >= 0) {
|
|
253689
|
+
const { src } = content2 || {};
|
|
253690
|
+
const { x: x2, y: y2, featureIndices } = src || {};
|
|
253691
|
+
return {
|
|
253692
|
+
pointIndex,
|
|
253693
|
+
x: x2?.[pointIndex],
|
|
253694
|
+
y: y2?.[pointIndex],
|
|
253695
|
+
featureIndex: featureIndices?.[pointIndex]
|
|
253696
|
+
};
|
|
253697
|
+
}
|
|
253334
253698
|
const { data: data2, width: width2, height: height2 } = content2;
|
|
253335
253699
|
const { left: left2, right: right2, top: top2, bottom: bottom2 } = bbox2;
|
|
253336
253700
|
const bounds2 = [
|
|
@@ -253508,6 +253872,8 @@ function SpatialSubscriber(props) {
|
|
|
253508
253872
|
CoordinationType$1.SPATIAL_LAYER_VISIBLE,
|
|
253509
253873
|
CoordinationType$1.SPATIAL_LAYER_OPACITY,
|
|
253510
253874
|
CoordinationType$1.OBS_COLOR_ENCODING,
|
|
253875
|
+
CoordinationType$1.FEATURE_COLOR,
|
|
253876
|
+
CoordinationType$1.FEATURE_FILTER_MODE,
|
|
253511
253877
|
CoordinationType$1.FEATURE_SELECTION,
|
|
253512
253878
|
CoordinationType$1.FEATURE_VALUE_COLORMAP,
|
|
253513
253879
|
CoordinationType$1.FEATURE_VALUE_COLORMAP_RANGE,
|
|
@@ -253518,7 +253884,10 @@ function SpatialSubscriber(props) {
|
|
|
253518
253884
|
CoordinationType$1.LEGEND_VISIBLE
|
|
253519
253885
|
], coordinationScopes, coordinationScopesBy, CoordinationType$1.POINT_LAYER);
|
|
253520
253886
|
const [volumeLoadingStatus, setVolumeLoadingStatus] = useState(null);
|
|
253521
|
-
const [{ volumeLoadingProgress }, { setVolumeLoadingProgress }] = useAuxiliaryCoordination([
|
|
253887
|
+
const [{ volumeLoadingProgress, tiledPointsLoadingProgress }, { setVolumeLoadingProgress, setTiledPointsLoadingProgress }] = useAuxiliaryCoordination([
|
|
253888
|
+
"spatialAcceleratedVolumeLoadingProgress",
|
|
253889
|
+
"spatialTiledPointsLoadingProgress"
|
|
253890
|
+
], coordinationScopes);
|
|
253522
253891
|
useEffect(() => {
|
|
253523
253892
|
if (volumeLoadingStatus && volumeLoadingStatus.loadingProgress) {
|
|
253524
253893
|
setVolumeLoadingProgress(volumeLoadingStatus);
|
|
@@ -253535,6 +253904,7 @@ function SpatialSubscriber(props) {
|
|
|
253535
253904
|
const height2 = threeFor3d && deckHeight === void 0 ? threeHeight : deckHeight;
|
|
253536
253905
|
const [obsPointsData, obsPointsDataStatus, obsPointsUrls, obsPointsErrors] = useMultiObsPoints(coordinationScopes, coordinationScopesBy, loaders, dataset, mergeCoordination, uuid2);
|
|
253537
253906
|
const [pointMultiObsLabelsData, pointMultiObsLabelsDataStatus, pointMultiObsLabelsErrors] = usePointMultiObsLabels(coordinationScopes, coordinationScopesBy, loaders, dataset);
|
|
253907
|
+
const [pointMultiIndicesData, pointMultiIndicesDataStatus, pointMultiIndicesDataErrors] = usePointMultiObsFeatureMatrixIndices(coordinationScopes, coordinationScopesBy, loaders, dataset);
|
|
253538
253908
|
const [obsSpotsData, obsSpotsDataStatus, obsSpotsUrls, obsSpotsErrors] = useMultiObsSpots(coordinationScopes, coordinationScopesBy, loaders, dataset, mergeCoordination, uuid2);
|
|
253539
253909
|
const [obsSpotsSetsData, obsSpotsSetsDataStatus, obsSpotSetsUrls, obsSpotsSetsErrors] = useSpotMultiObsSets(coordinationScopes, coordinationScopesBy, loaders, dataset);
|
|
253540
253910
|
const [obsSpotsFeatureLabelsData, obsSpotsFeatureLabelsDataStatus, obsSpotsFeatureLabelsUrls, obsSpotsFeatureLabelsErrors] = useSpotMultiFeatureLabels(coordinationScopes, coordinationScopesBy, loaders, dataset);
|
|
@@ -253568,6 +253938,7 @@ function SpatialSubscriber(props) {
|
|
|
253568
253938
|
...spotMultiFeatureSelectionErrors,
|
|
253569
253939
|
...spotMultiIndicesDataErrors,
|
|
253570
253940
|
...pointMultiObsLabelsErrors,
|
|
253941
|
+
...pointMultiIndicesDataErrors,
|
|
253571
253942
|
...segmentationMultiFeatureSelectionErrors,
|
|
253572
253943
|
...segmentationMultiIndicesDataErrors,
|
|
253573
253944
|
...obsSegmentationsLocationsDataErrors
|
|
@@ -253587,6 +253958,7 @@ function SpatialSubscriber(props) {
|
|
|
253587
253958
|
// Points
|
|
253588
253959
|
obsPointsDataStatus,
|
|
253589
253960
|
pointMultiObsLabelsDataStatus,
|
|
253961
|
+
pointMultiIndicesDataStatus,
|
|
253590
253962
|
// Segmentations
|
|
253591
253963
|
obsSegmentationsDataStatus,
|
|
253592
253964
|
obsSegmentationsSetsDataStatus,
|
|
@@ -253774,14 +254146,19 @@ function SpatialSubscriber(props) {
|
|
|
253774
254146
|
pointLayerScopes?.forEach((pointLayerScope) => {
|
|
253775
254147
|
const { setObsHighlight } = pointLayerCoordination?.[1]?.[pointLayerScope] || {};
|
|
253776
254148
|
if (hoverData && layerType === "point" && layerScope === pointLayerScope) {
|
|
253777
|
-
|
|
253778
|
-
const { obsIndex } = obsPointsData?.[pointLayerScope] || {};
|
|
253779
|
-
const obsId = obsIndex?.[obsI];
|
|
253780
|
-
if (obsIndex && obsId) {
|
|
254149
|
+
if (typeof hoverData === "object" && hoverData?.pointIndex) {
|
|
253781
254150
|
showAnyTooltip = true;
|
|
253782
|
-
setObsHighlight(
|
|
254151
|
+
setObsHighlight(hoverData.pointIndex);
|
|
253783
254152
|
} else {
|
|
253784
|
-
|
|
254153
|
+
const obsI = hoverData;
|
|
254154
|
+
const { obsIndex } = obsPointsData?.[pointLayerScope] || {};
|
|
254155
|
+
const obsId = obsIndex?.[obsI];
|
|
254156
|
+
if (obsIndex && obsId) {
|
|
254157
|
+
showAnyTooltip = true;
|
|
254158
|
+
setObsHighlight(obsId);
|
|
254159
|
+
} else {
|
|
254160
|
+
setObsHighlight(null);
|
|
254161
|
+
}
|
|
253785
254162
|
}
|
|
253786
254163
|
} else {
|
|
253787
254164
|
setObsHighlight(null);
|
|
@@ -253823,7 +254200,7 @@ function SpatialSubscriber(props) {
|
|
|
253823
254200
|
target: [targetX2, targetY2, targetZ],
|
|
253824
254201
|
rotationX,
|
|
253825
254202
|
rotationOrbit
|
|
253826
|
-
} : 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, {
|
|
254203
|
+
} : 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, {
|
|
253827
254204
|
parentUuid: uuid2,
|
|
253828
254205
|
width: width2,
|
|
253829
254206
|
height: height2,
|
|
@@ -253864,7 +254241,8 @@ function SpatialSubscriber(props) {
|
|
|
253864
254241
|
spotMultiFeatureLabels: obsSpotsFeatureLabelsData,
|
|
253865
254242
|
// Points
|
|
253866
254243
|
pointLayerScopes,
|
|
253867
|
-
pointLayerCoordination
|
|
254244
|
+
pointLayerCoordination,
|
|
254245
|
+
pointMultiIndicesData
|
|
253868
254246
|
}
|
|
253869
254247
|
), jsxRuntimeExports.jsx(
|
|
253870
254248
|
ChannelNamesLegend,
|
|
@@ -262826,17 +263204,35 @@ function SpotLayerController(props) {
|
|
|
262826
263204
|
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 }) })] }) }) });
|
|
262827
263205
|
}
|
|
262828
263206
|
const useStyles$e = makeStyles()(() => ({
|
|
263207
|
+
pointLayerButton: {
|
|
263208
|
+
borderStyle: "dashed",
|
|
263209
|
+
marginTop: "10px",
|
|
263210
|
+
marginBottom: "10px",
|
|
263211
|
+
fontWeight: 400
|
|
263212
|
+
},
|
|
263213
|
+
pointFeatureControllerGrid: {
|
|
263214
|
+
padding: "0",
|
|
263215
|
+
flexWrap: "nowrap"
|
|
263216
|
+
},
|
|
263217
|
+
pointFeatureExpansionButton: {
|
|
263218
|
+
display: "inline-block",
|
|
263219
|
+
margin: 0,
|
|
263220
|
+
padding: 0,
|
|
263221
|
+
minWidth: 0,
|
|
263222
|
+
lineHeight: 1,
|
|
263223
|
+
width: "50%"
|
|
263224
|
+
},
|
|
262829
263225
|
layerTypePointIcon: {
|
|
262830
263226
|
height: "100%",
|
|
262831
|
-
|
|
263227
|
+
paddingLeft: "2px",
|
|
262832
263228
|
fill: "currentColor",
|
|
262833
|
-
fontSize: "
|
|
263229
|
+
fontSize: "14px",
|
|
262834
263230
|
width: "50%",
|
|
262835
|
-
maxWidth: "
|
|
263231
|
+
maxWidth: "16px"
|
|
262836
263232
|
}
|
|
262837
263233
|
}));
|
|
262838
263234
|
function PointLayerEllipsisMenu(props) {
|
|
262839
|
-
const { featureSelection, obsColorEncoding, setObsColorEncoding, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible } = props;
|
|
263235
|
+
const { featureSelection, featureFilterMode, setFeatureFilterMode, obsColorEncoding, setObsColorEncoding, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible } = props;
|
|
262840
263236
|
const [open2, setOpen] = useState(false);
|
|
262841
263237
|
const { classes: selectClasses2 } = useSelectStyles();
|
|
262842
263238
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
@@ -262845,17 +263241,84 @@ function PointLayerEllipsisMenu(props) {
|
|
|
262845
263241
|
const tooltipsVisibleId = $bdb11010cef70236$export$f680877a34711e37();
|
|
262846
263242
|
const crosshairsVisibleId = $bdb11010cef70236$export$f680877a34711e37();
|
|
262847
263243
|
const legendVisibleId = $bdb11010cef70236$export$f680877a34711e37();
|
|
262848
|
-
|
|
263244
|
+
const featureFilterModeId = $bdb11010cef70236$export$f680877a34711e37();
|
|
263245
|
+
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" } } })] })] });
|
|
262849
263246
|
}
|
|
262850
263247
|
function PointLayerController(props) {
|
|
262851
|
-
const { theme, layerScope, layerCoordination, setLayerCoordination, palette = null } = props;
|
|
262852
|
-
const
|
|
262853
|
-
const
|
|
263248
|
+
const { theme, layerScope, layerCoordination, setLayerCoordination, palette = null, pointMatrixIndicesData, tiledPointsLoadingProgress } = props;
|
|
263249
|
+
const [open2, setOpen] = useState(false);
|
|
263250
|
+
const loadingDoneFraction = useMemo$1(() => {
|
|
263251
|
+
if (tiledPointsLoadingProgress && typeof tiledPointsLoadingProgress === "object") {
|
|
263252
|
+
return 1 - Object.values(tiledPointsLoadingProgress).filter((status) => status === "loading").length / Object.values(tiledPointsLoadingProgress).length;
|
|
263253
|
+
}
|
|
263254
|
+
return 1;
|
|
263255
|
+
}, [tiledPointsLoadingProgress]);
|
|
263256
|
+
const { obsType, spatialLayerVisible: visible, spatialLayerOpacity: opacity2, obsColorEncoding, featureColor, featureFilterMode, featureSelection, featureValueColormap, featureValueColormapRange, spatialLayerColor, tooltipsVisible, tooltipCrosshairsVisible, legendVisible } = layerCoordination;
|
|
263257
|
+
const { setSpatialLayerVisible: setVisible, setSpatialLayerOpacity: setOpacity2, setObsColorEncoding, setFeatureColor, setFeatureFilterMode, setFeatureSelection, setFeatureValueColormap, setFeatureValueColormapRange, setSpatialLayerColor, setTooltipsVisible, setTooltipCrosshairsVisible, setLegendVisible } = setLayerCoordination;
|
|
262854
263258
|
const label2 = capitalize$3(obsType);
|
|
262855
263259
|
const visibleSetting = typeof visible === "boolean" ? visible : true;
|
|
262856
263260
|
const Visibility = useMemo$1(() => visibleSetting ? VisibilityIcon : VisibilityOffIcon, [visibleSetting]);
|
|
262857
|
-
const
|
|
262858
|
-
|
|
263261
|
+
const hasUnspecifiedFeatureColors = useMemo$1(() => {
|
|
263262
|
+
if (Array.isArray(featureSelection)) {
|
|
263263
|
+
if (Array.isArray(featureColor)) {
|
|
263264
|
+
return featureSelection.some((featureName) => {
|
|
263265
|
+
const colorForFeature = featureColor.find((fc) => fc.name === featureName);
|
|
263266
|
+
return !colorForFeature;
|
|
263267
|
+
});
|
|
263268
|
+
}
|
|
263269
|
+
return featureSelection.length > 0;
|
|
263270
|
+
}
|
|
263271
|
+
return true;
|
|
263272
|
+
}, [featureColor, featureSelection]);
|
|
263273
|
+
const isStaticColor = obsColorEncoding === "spatialLayerColor" || obsColorEncoding === "geneSelection";
|
|
263274
|
+
const showStaticColor = obsColorEncoding === "spatialLayerColor" || obsColorEncoding === "geneSelection" && hasUnspecifiedFeatureColors;
|
|
263275
|
+
const isColormap = false;
|
|
263276
|
+
const hasSingleSelectedFeature = obsColorEncoding === "geneSelection" && Array.isArray(featureSelection) && featureSelection.length === 1;
|
|
263277
|
+
const color2 = useMemo$1(() => {
|
|
263278
|
+
if (showStaticColor) {
|
|
263279
|
+
return spatialLayerColor;
|
|
263280
|
+
}
|
|
263281
|
+
if (hasSingleSelectedFeature) {
|
|
263282
|
+
const selectedFeatureColor = featureColor?.find((fc) => fc.name === featureSelection[0])?.color;
|
|
263283
|
+
if (selectedFeatureColor) {
|
|
263284
|
+
return selectedFeatureColor;
|
|
263285
|
+
}
|
|
263286
|
+
}
|
|
263287
|
+
return null;
|
|
263288
|
+
}, [
|
|
263289
|
+
hasSingleSelectedFeature,
|
|
263290
|
+
spatialLayerColor,
|
|
263291
|
+
featureColor,
|
|
263292
|
+
featureSelection,
|
|
263293
|
+
showStaticColor
|
|
263294
|
+
]);
|
|
263295
|
+
const setColor2 = useCallback((newColor) => {
|
|
263296
|
+
if (showStaticColor) {
|
|
263297
|
+
setSpatialLayerColor(newColor);
|
|
263298
|
+
} else if (hasSingleSelectedFeature) {
|
|
263299
|
+
const featureColorIndex = featureColor?.findIndex((fc) => fc.name === featureSelection[0]);
|
|
263300
|
+
if (featureColorIndex !== void 0 && featureColorIndex >= 0) {
|
|
263301
|
+
const newFeatureColor = [...featureColor];
|
|
263302
|
+
newFeatureColor[featureColorIndex] = {
|
|
263303
|
+
name: featureSelection[0],
|
|
263304
|
+
color: newColor
|
|
263305
|
+
};
|
|
263306
|
+
setFeatureColor(newFeatureColor);
|
|
263307
|
+
} else {
|
|
263308
|
+
setFeatureColor([
|
|
263309
|
+
...featureColor,
|
|
263310
|
+
{ name: featureSelection[0], color: newColor }
|
|
263311
|
+
]);
|
|
263312
|
+
}
|
|
263313
|
+
}
|
|
263314
|
+
}, [
|
|
263315
|
+
hasSingleSelectedFeature,
|
|
263316
|
+
setSpatialLayerColor,
|
|
263317
|
+
featureColor,
|
|
263318
|
+
setFeatureColor,
|
|
263319
|
+
featureSelection,
|
|
263320
|
+
showStaticColor
|
|
263321
|
+
]);
|
|
262859
263322
|
const { classes: classes2 } = useStyles$e();
|
|
262860
263323
|
const { classes: lcClasses } = useControllerSectionStyles();
|
|
262861
263324
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
@@ -262864,7 +263327,10 @@ function PointLayerController(props) {
|
|
|
262864
263327
|
setVisible(nextVisible);
|
|
262865
263328
|
}, [visible, setVisible]);
|
|
262866
263329
|
const handleOpacityChange = useCallback((e3, v) => setOpacity2(v), [setOpacity2]);
|
|
262867
|
-
|
|
263330
|
+
useCallback(() => setOpen((prev2) => !prev2), []);
|
|
263331
|
+
const [coloringTabIndex, setColoringTabIndex] = useState(0);
|
|
263332
|
+
const { featureIndex } = pointMatrixIndicesData || {};
|
|
263333
|
+
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] }) });
|
|
262868
263334
|
}
|
|
262869
263335
|
const useStyles$d = makeStyles()(() => ({
|
|
262870
263336
|
layerTypeSegmentationIcon: {
|
|
@@ -264395,7 +264861,7 @@ function ImageLayerEllipsisMenu(props) {
|
|
|
264395
264861
|
const { classes: selectClasses2 } = useSelectStyles();
|
|
264396
264862
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
264397
264863
|
const [localLodSliderValue, setLocalLodSliderValue] = useState(convertLodFactorToLogarithmicSliderValue(spatialLodFactor || 1));
|
|
264398
|
-
|
|
264864
|
+
useEffect(() => {
|
|
264399
264865
|
setLocalLodSliderValue(convertLodFactorToLogarithmicSliderValue(spatialLodFactor || 1));
|
|
264400
264866
|
}, [spatialLodFactor]);
|
|
264401
264867
|
const is3dMode = spatialRenderingMode === "3D";
|
|
@@ -264531,7 +264997,7 @@ function GlobalDimensionSlider(props) {
|
|
|
264531
264997
|
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 })] }) }) });
|
|
264532
264998
|
}
|
|
264533
264999
|
function LayerController(props) {
|
|
264534
|
-
const { theme, coordinationScopesRaw, segmentationLayerScopes, segmentationLayerCoordination, segmentationChannelScopesByLayer, segmentationChannelCoordination, images, imageLayerScopes, imageLayerCoordination, targetT, targetZ, setTargetT, setTargetZ, spatialRenderingMode, setSpatialRenderingMode, imageChannelScopesByLayer, imageChannelCoordination, spotLayerScopes, spotLayerCoordination, pointLayerScopes, pointLayerCoordination, volumeLoadingStatus } = props;
|
|
265000
|
+
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;
|
|
264535
265001
|
const anyLayerHasT = Object.values(images || {}).some((image2) => image2?.image?.instance.hasTStack());
|
|
264536
265002
|
const anyLayerHasZ = Object.values(images || {}).some((image2) => image2?.image?.instance.hasZStack());
|
|
264537
265003
|
const maxT = Object.values(images || {}).reduce((a2, h2) => Math.max(a2, h2?.image?.instance.getNumT()), 1) - 1;
|
|
@@ -264540,7 +265006,7 @@ function LayerController(props) {
|
|
|
264540
265006
|
const reversedSegmentationLayerScopes = useMemo$1(() => [...segmentationLayerScopes || []].reverse(), [segmentationLayerScopes]);
|
|
264541
265007
|
const reversedSpotLayerScopes = useMemo$1(() => [...spotLayerScopes || []].reverse(), [spotLayerScopes]);
|
|
264542
265008
|
const reversedPointLayerScopes = useMemo$1(() => [...pointLayerScopes || []].reverse(), [pointLayerScopes]);
|
|
264543
|
-
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))] });
|
|
265009
|
+
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))] });
|
|
264544
265010
|
}
|
|
264545
265011
|
function LayerControllerSubscriber(props) {
|
|
264546
265012
|
const { coordinationScopes: coordinationScopesRaw, coordinationScopesBy: coordinationScopesByRaw, closeButtonVisible, downloadButtonVisible, removeGridComponent, theme, title: title2 = "Spatial Layers", uuid: uuid2 } = props;
|
|
@@ -264624,6 +265090,8 @@ function LayerControllerSubscriber(props) {
|
|
|
264624
265090
|
CoordinationType$1.SPATIAL_LAYER_OPACITY,
|
|
264625
265091
|
CoordinationType$1.SPATIAL_SPOT_RADIUS,
|
|
264626
265092
|
CoordinationType$1.OBS_COLOR_ENCODING,
|
|
265093
|
+
CoordinationType$1.FEATURE_COLOR,
|
|
265094
|
+
CoordinationType$1.FEATURE_FILTER_MODE,
|
|
264627
265095
|
CoordinationType$1.FEATURE_SELECTION,
|
|
264628
265096
|
CoordinationType$1.FEATURE_VALUE_COLORMAP,
|
|
264629
265097
|
CoordinationType$1.FEATURE_VALUE_COLORMAP_RANGE,
|
|
@@ -264632,7 +265100,10 @@ function LayerControllerSubscriber(props) {
|
|
|
264632
265100
|
CoordinationType$1.TOOLTIP_CROSSHAIRS_VISIBLE,
|
|
264633
265101
|
CoordinationType$1.LEGEND_VISIBLE
|
|
264634
265102
|
], coordinationScopes, coordinationScopesBy, CoordinationType$1.POINT_LAYER);
|
|
264635
|
-
const [{ volumeLoadingProgress: volumeLoadingStatus }] = useAuxiliaryCoordination([
|
|
265103
|
+
const [{ volumeLoadingProgress: volumeLoadingStatus, tiledPointsLoadingProgress }] = useAuxiliaryCoordination([
|
|
265104
|
+
"spatialAcceleratedVolumeLoadingProgress",
|
|
265105
|
+
"spatialTiledPointsLoadingProgress"
|
|
265106
|
+
], coordinationScopes);
|
|
264636
265107
|
const [spatialLayout] = useComponentLayout("spatial", ["spatialImageLayer"], coordinationScopes);
|
|
264637
265108
|
const layerControllerRef = useRef();
|
|
264638
265109
|
const [componentWidth, componentHeight] = useClosestVitessceContainerSize(layerControllerRef);
|
|
@@ -264641,19 +265112,22 @@ function LayerControllerSubscriber(props) {
|
|
|
264641
265112
|
const [imageData, imageDataStatus, imageUrls, imageErrors] = useMultiImages(coordinationScopes, coordinationScopesBy, loaders, dataset, mergeCoordination, uuid2);
|
|
264642
265113
|
const [obsSpotsData, obsSpotsDataStatus, obsSpotsUrls, obsSpotsErrors] = useMultiObsSpots(coordinationScopes, coordinationScopesBy, loaders, dataset, mergeCoordination, uuid2);
|
|
264643
265114
|
const [obsPointsData, obsPointsDataStatus, obsPointsUrls, obsPointsErrors] = useMultiObsPoints(coordinationScopes, coordinationScopesBy, loaders, dataset, mergeCoordination, uuid2);
|
|
265115
|
+
const [pointMultiIndicesData, pointMultiIndicesDataStatus, pointMultiIndicesDataErrors] = usePointMultiObsFeatureMatrixIndices(coordinationScopes, coordinationScopesBy, loaders, dataset);
|
|
264644
265116
|
const errors = [
|
|
264645
265117
|
...obsSegmentationsErrors,
|
|
264646
265118
|
...imageErrors,
|
|
264647
265119
|
...obsSpotsErrors,
|
|
264648
|
-
...obsPointsErrors
|
|
265120
|
+
...obsPointsErrors,
|
|
265121
|
+
...pointMultiIndicesDataErrors
|
|
264649
265122
|
];
|
|
264650
265123
|
const isReady = useReady([
|
|
264651
265124
|
obsSpotsDataStatus,
|
|
264652
265125
|
obsPointsDataStatus,
|
|
264653
265126
|
obsSegmentationsDataStatus,
|
|
264654
|
-
imageDataStatus
|
|
265127
|
+
imageDataStatus,
|
|
265128
|
+
pointMultiIndicesDataStatus
|
|
264655
265129
|
]);
|
|
264656
|
-
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 }) });
|
|
265130
|
+
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 }) });
|
|
264657
265131
|
}
|
|
264658
265132
|
const isIterable$2 = (obj) => Symbol.iterator in obj;
|
|
264659
265133
|
const hasIterableEntries = (value2) => (
|
|
@@ -266568,7 +267042,7 @@ function HiglassGlobalStyles(props) {
|
|
|
266568
267042
|
}
|
|
266569
267043
|
register({ dataFetcher: ZarrMultivecDataFetcher_default, config: ZarrMultivecDataFetcher_default.config }, { pluginType: "dataFetcher" });
|
|
266570
267044
|
const LazyHiGlassComponent = React__default.lazy(async () => {
|
|
266571
|
-
const { HiGlassComponent } = await import("./higlass-
|
|
267045
|
+
const { HiGlassComponent } = await import("./higlass-Chx9S58D.js");
|
|
266572
267046
|
return { default: HiGlassComponent };
|
|
266573
267047
|
});
|
|
266574
267048
|
const HG_SIZE = 800;
|
|
@@ -269515,7 +269989,7 @@ function NeuroglancerGlobalStyles(props) {
|
|
|
269515
269989
|
const { classes: classes2 } = props;
|
|
269516
269990
|
return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(GlobalStyles$3, { styles: globalNeuroglancerCss }), jsxRuntimeExports.jsx(ScopedGlobalStyles, { styles: globalNeuroglancerStyles, parentClassName: classes2.neuroglancerWrapper })] });
|
|
269517
269991
|
}
|
|
269518
|
-
const LazyReactNeuroglancer = React__default.lazy(() => import("./ReactNeuroglancer-
|
|
269992
|
+
const LazyReactNeuroglancer = React__default.lazy(() => import("./ReactNeuroglancer-rd4zjvRk.js"));
|
|
269519
269993
|
function createWorker() {
|
|
269520
269994
|
return new WorkerFactory();
|
|
269521
269995
|
}
|
|
@@ -290689,7 +291163,7 @@ function cureLocalIntersections(start2, triangles, dim) {
|
|
|
290689
291163
|
let p = start2;
|
|
290690
291164
|
do {
|
|
290691
291165
|
const a2 = p.prev, b2 = p.next.next;
|
|
290692
|
-
if (!equals$1(a2, b2) && intersects$
|
|
291166
|
+
if (!equals$1(a2, b2) && intersects$3(a2, p, p.next, b2) && locallyInside(a2, b2) && locallyInside(b2, a2)) {
|
|
290693
291167
|
triangles.push(a2.i / dim | 0);
|
|
290694
291168
|
triangles.push(p.i / dim | 0);
|
|
290695
291169
|
triangles.push(b2.i / dim | 0);
|
|
@@ -290867,7 +291341,7 @@ function area$3(p, q, r3) {
|
|
|
290867
291341
|
function equals$1(p1, p2) {
|
|
290868
291342
|
return p1.x === p2.x && p1.y === p2.y;
|
|
290869
291343
|
}
|
|
290870
|
-
function intersects$
|
|
291344
|
+
function intersects$3(p1, q1, p2, q2) {
|
|
290871
291345
|
const o1 = sign$2(area$3(p1, q1, p2));
|
|
290872
291346
|
const o2 = sign$2(area$3(p1, q1, q2));
|
|
290873
291347
|
const o3 = sign$2(area$3(p2, q2, p1));
|
|
@@ -290888,7 +291362,7 @@ function sign$2(num) {
|
|
|
290888
291362
|
function intersectsPolygon(a2, b2) {
|
|
290889
291363
|
let p = a2;
|
|
290890
291364
|
do {
|
|
290891
|
-
if (p.i !== a2.i && p.next.i !== a2.i && p.i !== b2.i && p.next.i !== b2.i && intersects$
|
|
291365
|
+
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;
|
|
290892
291366
|
p = p.next;
|
|
290893
291367
|
} while (p !== a2);
|
|
290894
291368
|
return false;
|
|
@@ -319899,7 +320373,7 @@ function place(b2, a2, c2) {
|
|
|
319899
320373
|
c2.y = a2.y;
|
|
319900
320374
|
}
|
|
319901
320375
|
}
|
|
319902
|
-
function intersects$
|
|
320376
|
+
function intersects$2(a2, b2) {
|
|
319903
320377
|
var dr = a2.r + b2.r - 1e-6, dx = b2.x - a2.x, dy = b2.y - a2.y;
|
|
319904
320378
|
return dr > 0 && dr * dr > dx * dx + dy * dy;
|
|
319905
320379
|
}
|
|
@@ -319929,13 +320403,13 @@ function packSiblingsRandom(circles, random2) {
|
|
|
319929
320403
|
j = b2.next, k = a2.previous, sj = b2._.r, sk = a2._.r;
|
|
319930
320404
|
do {
|
|
319931
320405
|
if (sj <= sk) {
|
|
319932
|
-
if (intersects$
|
|
320406
|
+
if (intersects$2(j._, c2._)) {
|
|
319933
320407
|
b2 = j, a2.next = b2, b2.previous = a2, --i2;
|
|
319934
320408
|
continue pack;
|
|
319935
320409
|
}
|
|
319936
320410
|
sj += j._.r, j = j.next;
|
|
319937
320411
|
} else {
|
|
319938
|
-
if (intersects$
|
|
320412
|
+
if (intersects$2(k._, c2._)) {
|
|
319939
320413
|
a2 = k, a2.next = b2, b2.previous = a2, --i2;
|
|
319940
320414
|
continue pack;
|
|
319941
320415
|
}
|
|
@@ -354680,7 +355154,7 @@ class ObsPointsCsvLoader extends CsvLoader {
|
|
|
354680
355154
|
data: [obsLocationsX, obsLocationsY],
|
|
354681
355155
|
shape: [2, obsLocationsX.length]
|
|
354682
355156
|
};
|
|
354683
|
-
this.cachedResult = { obsIndex, obsPoints };
|
|
355157
|
+
this.cachedResult = { obsIndex, obsPoints, obsPointsTilingType: "full" };
|
|
354684
355158
|
return this.cachedResult;
|
|
354685
355159
|
}
|
|
354686
355160
|
async load() {
|
|
@@ -356312,7 +356786,7 @@ class ObsPointsAnndataLoader extends AbstractTwoStepLoader {
|
|
|
356312
356786
|
this.dataSource.loadObsIndex(path2),
|
|
356313
356787
|
this.loadPoints()
|
|
356314
356788
|
]);
|
|
356315
|
-
return new LoaderResult({ obsIndex, obsPoints }, null, coordinationValues);
|
|
356789
|
+
return new LoaderResult({ obsIndex, obsPoints, obsPointsTilingType: "full" }, null, coordinationValues);
|
|
356316
356790
|
}
|
|
356317
356791
|
}
|
|
356318
356792
|
class ObsLocationsAnndataLoader extends AbstractTwoStepLoader {
|
|
@@ -357929,6 +358403,17 @@ class SpatialDataObsPointsLoader extends AbstractTwoStepLoader {
|
|
|
357929
358403
|
this.locations = locations;
|
|
357930
358404
|
return this.locations;
|
|
357931
358405
|
}
|
|
358406
|
+
async loadPointsInRect(bounds2, signal) {
|
|
358407
|
+
const { path: path2 } = this.options;
|
|
358408
|
+
let locations;
|
|
358409
|
+
const formatVersion = await this.dataSource.getPointsFormatVersion(path2);
|
|
358410
|
+
if (formatVersion === "0.1") {
|
|
358411
|
+
locations = await this.dataSource.loadPointsInRect(path2, bounds2, signal);
|
|
358412
|
+
} else {
|
|
358413
|
+
throw new UnknownSpatialDataFormatError("Only points format version 0.1 is supported.");
|
|
358414
|
+
}
|
|
358415
|
+
return locations;
|
|
358416
|
+
}
|
|
357932
358417
|
async loadObsIndex() {
|
|
357933
358418
|
const { tablePath, path: path2 } = this.options;
|
|
357934
358419
|
if (tablePath) {
|
|
@@ -357941,11 +358426,26 @@ class SpatialDataObsPointsLoader extends AbstractTwoStepLoader {
|
|
|
357941
358426
|
}
|
|
357942
358427
|
return null;
|
|
357943
358428
|
}
|
|
358429
|
+
async supportsTiling() {
|
|
358430
|
+
const { path: path2 } = this.options;
|
|
358431
|
+
const [formatVersion, zattrs, hasRequiredColumnsAndRowGroupSize] = await Promise.all([
|
|
358432
|
+
// Check the points format version.
|
|
358433
|
+
this.dataSource.getPointsFormatVersion(path2),
|
|
358434
|
+
// Check for the presence of bounding_box metadata.
|
|
358435
|
+
this.dataSource.loadSpatialDataElementAttrs(path2),
|
|
358436
|
+
// Check the size of parquet row groups,
|
|
358437
|
+
// and for the presence of morton_code_2d and feature_index columns.
|
|
358438
|
+
this.dataSource.supportsLoadPointsInRect(path2)
|
|
358439
|
+
]);
|
|
358440
|
+
const isSupportedVersion = formatVersion === "0.1";
|
|
358441
|
+
const boundingBox = zattrs?.bounding_box;
|
|
358442
|
+
const hasBoundingBox2D = typeof boundingBox?.x_max === "number" && typeof boundingBox?.x_min === "number" && typeof boundingBox?.y_max === "number" && typeof boundingBox?.y_min === "number";
|
|
358443
|
+
return isSupportedVersion && hasBoundingBox2D && hasRequiredColumnsAndRowGroupSize;
|
|
358444
|
+
}
|
|
357944
358445
|
async load() {
|
|
357945
|
-
const [
|
|
357946
|
-
this.
|
|
357947
|
-
this.
|
|
357948
|
-
this.loadModelMatrix()
|
|
358446
|
+
const [modelMatrix2, supportsTiling] = await Promise.all([
|
|
358447
|
+
this.loadModelMatrix(),
|
|
358448
|
+
this.supportsTiling()
|
|
357949
358449
|
]);
|
|
357950
358450
|
const coordinationValues = {
|
|
357951
358451
|
pointLayer: CL({
|
|
@@ -357961,7 +358461,36 @@ class SpatialDataObsPointsLoader extends AbstractTwoStepLoader {
|
|
|
357961
358461
|
// additionalObsSets: null,
|
|
357962
358462
|
})
|
|
357963
358463
|
};
|
|
357964
|
-
|
|
358464
|
+
let obsIndex = null;
|
|
358465
|
+
let obsPoints = null;
|
|
358466
|
+
const featureIndices = null;
|
|
358467
|
+
if (!supportsTiling) {
|
|
358468
|
+
[obsIndex, obsPoints] = await Promise.all([
|
|
358469
|
+
this.loadObsIndex(),
|
|
358470
|
+
this.loadPoints()
|
|
358471
|
+
]);
|
|
358472
|
+
}
|
|
358473
|
+
return new LoaderResult({
|
|
358474
|
+
/* obsIndex: ["1"], // TEMP
|
|
358475
|
+
obsPoints: { // TEMP
|
|
358476
|
+
shape: [2, 1],
|
|
358477
|
+
data: [[0], [0]],
|
|
358478
|
+
}, */
|
|
358479
|
+
// These will be null if tiling is supported.
|
|
358480
|
+
obsIndex,
|
|
358481
|
+
obsPoints,
|
|
358482
|
+
featureIndices,
|
|
358483
|
+
obsPointsModelMatrix: modelMatrix2,
|
|
358484
|
+
// Return 'tiled' if the morton_code_2d column
|
|
358485
|
+
// and bounding_box metadata are present,
|
|
358486
|
+
// and the row group size is small enough.
|
|
358487
|
+
// Otherwise, return 'full'.
|
|
358488
|
+
obsPointsTilingType: supportsTiling ? "tiled" : "full",
|
|
358489
|
+
// TEMPORARY: probably makes more sense to pass the loader instance all the way down.
|
|
358490
|
+
// Caller can then decide whether to use loader.load vs. loader.loadPointsInRect.
|
|
358491
|
+
// May need another function such as loader.supportsPointInRect() true/false.
|
|
358492
|
+
loadPointsInRect: this.loadPointsInRect.bind(this)
|
|
358493
|
+
}, null, coordinationValues);
|
|
357965
358494
|
}
|
|
357966
358495
|
}
|
|
357967
358496
|
class SpatialDataObsSetsLoader extends ObsSetsAnndataLoader {
|
|
@@ -367356,13 +367885,470 @@ function tableFromIPC(input) {
|
|
|
367356
367885
|
}
|
|
367357
367886
|
return new Table(reader.readAll());
|
|
367358
367887
|
}
|
|
367888
|
+
const MORTON_CODE_NUM_BITS = 32;
|
|
367889
|
+
const MORTON_CODE_VALUE_MAX = 2 ** (MORTON_CODE_NUM_BITS / 2) - 1;
|
|
367890
|
+
function origCoordToNormCoord(origCoord, origXMin, origXMax, origYMin, origYMax) {
|
|
367891
|
+
const [origX, origY] = origCoord;
|
|
367892
|
+
const origXRange = origXMax - origXMin;
|
|
367893
|
+
const origYRange = origYMax - origYMin;
|
|
367894
|
+
return [
|
|
367895
|
+
// Clamp to zero at low end, since using unsigned ints.
|
|
367896
|
+
Math.max(Math.floor((origX - origXMin) / origXRange * MORTON_CODE_VALUE_MAX), 0),
|
|
367897
|
+
Math.max(Math.floor((origY - origYMin) / origYRange * MORTON_CODE_VALUE_MAX), 0)
|
|
367898
|
+
];
|
|
367899
|
+
}
|
|
367900
|
+
function intersects$1(ax0, ay0, ax1, ay1, bx0, by0, bx1, by1) {
|
|
367901
|
+
return !(ax1 < bx0 || bx1 < ax0 || ay1 < by0 || by1 < ay0);
|
|
367902
|
+
}
|
|
367903
|
+
function contained(ix0, iy0, ix1, iy1, ox0, oy0, ox1, oy1) {
|
|
367904
|
+
return ox0 <= ix0 && ix0 <= ix1 && ix1 <= ox1 && (oy0 <= iy0 && iy0 <= iy1 && iy1 <= oy1);
|
|
367905
|
+
}
|
|
367906
|
+
function pointInside(x2, y2, rx0, ry0, rx1, ry1) {
|
|
367907
|
+
return rx0 <= x2 && x2 <= rx1 && (ry0 <= y2 && y2 <= ry1);
|
|
367908
|
+
}
|
|
367909
|
+
function cellRange(prefix2, level, bits) {
|
|
367910
|
+
const shift2 = 2 * (bits - level);
|
|
367911
|
+
const power = 2 ** shift2;
|
|
367912
|
+
const lo = prefix2 * power;
|
|
367913
|
+
const hi = (prefix2 + 1) * power - 1;
|
|
367914
|
+
return [lo, hi];
|
|
367915
|
+
}
|
|
367916
|
+
function mergeAdjacent(intervals2) {
|
|
367917
|
+
if (intervals2.length === 0) {
|
|
367918
|
+
return [];
|
|
367919
|
+
}
|
|
367920
|
+
intervals2.sort((a2, b2) => a2[0] - b2[0]);
|
|
367921
|
+
const merged = [intervals2[0]];
|
|
367922
|
+
for (let i2 = 1; i2 < intervals2.length; i2++) {
|
|
367923
|
+
const [lo, hi] = intervals2[i2];
|
|
367924
|
+
const [mlo, mhi] = merged[merged.length - 1];
|
|
367925
|
+
if (lo <= mhi + 1) {
|
|
367926
|
+
merged[merged.length - 1] = [mlo, Math.max(mhi, hi)];
|
|
367927
|
+
} else {
|
|
367928
|
+
merged.push([lo, hi]);
|
|
367929
|
+
}
|
|
367930
|
+
}
|
|
367931
|
+
return merged;
|
|
367932
|
+
}
|
|
367933
|
+
function zcoverRectangle(rx0, ry0, rx1, ry1, bits, stopLevel = null, merge2 = true) {
|
|
367934
|
+
const maxCoord = (1 << bits) - 1;
|
|
367935
|
+
if (!(rx0 >= 0 && rx0 <= rx1 && rx1 <= maxCoord && ry0 >= 0 && ry0 <= ry1 && ry1 <= maxCoord)) {
|
|
367936
|
+
throw new Error("Rectangle out of bounds for given bits.");
|
|
367937
|
+
}
|
|
367938
|
+
const intervals2 = [];
|
|
367939
|
+
const stack2 = [[0, 0, 0, 0, maxCoord, maxCoord]];
|
|
367940
|
+
while (stack2.length > 0) {
|
|
367941
|
+
const [prefix2, level, xmin, ymin, xmax, ymax] = stack2.pop();
|
|
367942
|
+
if (!intersects$1(xmin, ymin, xmax, ymax, rx0, ry0, rx1, ry1)) {
|
|
367943
|
+
continue;
|
|
367944
|
+
}
|
|
367945
|
+
if (stopLevel !== null && level === stopLevel) {
|
|
367946
|
+
intervals2.push(cellRange(prefix2, level, bits));
|
|
367947
|
+
continue;
|
|
367948
|
+
}
|
|
367949
|
+
if (contained(xmin, ymin, xmax, ymax, rx0, ry0, rx1, ry1)) {
|
|
367950
|
+
intervals2.push(cellRange(prefix2, level, bits));
|
|
367951
|
+
continue;
|
|
367952
|
+
}
|
|
367953
|
+
if (level === bits) {
|
|
367954
|
+
if (pointInside(xmin, ymin, rx0, ry0, rx1, ry1)) {
|
|
367955
|
+
intervals2.push(cellRange(prefix2, level, bits));
|
|
367956
|
+
}
|
|
367957
|
+
continue;
|
|
367958
|
+
}
|
|
367959
|
+
const midx = Math.floor((xmin + xmax) / 2);
|
|
367960
|
+
const midy = Math.floor((ymin + ymax) / 2);
|
|
367961
|
+
stack2.push([prefix2 << 2 | 0, level + 1, xmin, ymin, midx, midy]);
|
|
367962
|
+
stack2.push([prefix2 << 2 | 1, level + 1, midx + 1, ymin, xmax, midy]);
|
|
367963
|
+
stack2.push([prefix2 << 2 | 2, level + 1, xmin, midy + 1, midx, ymax]);
|
|
367964
|
+
stack2.push([prefix2 << 2 | 3, level + 1, midx + 1, midy + 1, xmax, ymax]);
|
|
367965
|
+
}
|
|
367966
|
+
return merge2 ? mergeAdjacent(intervals2) : intervals2;
|
|
367967
|
+
}
|
|
367968
|
+
function sdataMortonQueryRectAux(boundingBox, origRect) {
|
|
367969
|
+
const xMin = boundingBox.x_min;
|
|
367970
|
+
const xMax = boundingBox.x_max;
|
|
367971
|
+
const yMin = boundingBox.y_min;
|
|
367972
|
+
const yMax = boundingBox.y_max;
|
|
367973
|
+
const normRect = [
|
|
367974
|
+
origCoordToNormCoord(origRect[0], xMin, xMax, yMin, yMax),
|
|
367975
|
+
origCoordToNormCoord(origRect[1], xMin, xMax, yMin, yMax)
|
|
367976
|
+
];
|
|
367977
|
+
const mortonIntervals = zcoverRectangle(normRect[0][0], normRect[0][1], normRect[1][0], normRect[1][1], 16, null, true);
|
|
367978
|
+
return mortonIntervals;
|
|
367979
|
+
}
|
|
367359
367980
|
async function getParquetModule() {
|
|
367360
367981
|
const module2 = await import(
|
|
367361
367982
|
/* webpackIgnore: true */
|
|
367362
|
-
"https://
|
|
367983
|
+
"https://cdn.vitessce.io/parquet-wasm@2c23652/esm/parquet_wasm.js"
|
|
367363
367984
|
);
|
|
367364
367985
|
await module2.default();
|
|
367365
|
-
return {
|
|
367986
|
+
return {
|
|
367987
|
+
readParquet: module2.readParquet,
|
|
367988
|
+
readSchema: module2.readSchema,
|
|
367989
|
+
readMetadata: module2.readMetadata,
|
|
367990
|
+
// Added in fork
|
|
367991
|
+
readParquetRowGroup: module2.readParquetRowGroup
|
|
367992
|
+
// Added in fork
|
|
367993
|
+
};
|
|
367994
|
+
}
|
|
367995
|
+
async function _getParquetModule({ queryClient }) {
|
|
367996
|
+
return queryClient.fetchQuery({
|
|
367997
|
+
queryKey: ["parquetModule"],
|
|
367998
|
+
staleTime: Infinity,
|
|
367999
|
+
queryFn: getParquetModule,
|
|
368000
|
+
meta: { queryClient }
|
|
368001
|
+
});
|
|
368002
|
+
}
|
|
368003
|
+
async function _loadParquetBytes({ queryClient, store }, parquetPath, rangeQuery = void 0, partIndex = void 0) {
|
|
368004
|
+
return queryClient.fetchQuery({
|
|
368005
|
+
queryKey: ["SpatialDataTableSource", "_loadParquetBytes", parquetPath, rangeQuery, partIndex],
|
|
368006
|
+
staleTime: Infinity,
|
|
368007
|
+
queryFn: async (ctx) => {
|
|
368008
|
+
const store2 = ctx.meta?.store;
|
|
368009
|
+
const rangeQuery2 = ctx.queryKey[3];
|
|
368010
|
+
const { offset: offset2, length: length2, suffixLength } = rangeQuery2 || {};
|
|
368011
|
+
let getter2 = (path2) => store2.get(path2);
|
|
368012
|
+
if (rangeQuery2 !== void 0 && store2.getRange) {
|
|
368013
|
+
if (suffixLength !== void 0) {
|
|
368014
|
+
getter2 = (path2) => store2.getRange(path2, {
|
|
368015
|
+
suffixLength
|
|
368016
|
+
});
|
|
368017
|
+
} else {
|
|
368018
|
+
getter2 = (path2) => store2.getRange(path2, {
|
|
368019
|
+
offset: offset2,
|
|
368020
|
+
length: length2
|
|
368021
|
+
});
|
|
368022
|
+
}
|
|
368023
|
+
}
|
|
368024
|
+
let parquetBytes;
|
|
368025
|
+
if (partIndex === void 0) {
|
|
368026
|
+
parquetBytes = await getter2(`/${parquetPath}`);
|
|
368027
|
+
}
|
|
368028
|
+
if (!parquetBytes) {
|
|
368029
|
+
const part0Path = `${parquetPath}/part.${partIndex ?? 0}.parquet`;
|
|
368030
|
+
parquetBytes = await getter2(`/${part0Path}`);
|
|
368031
|
+
}
|
|
368032
|
+
return parquetBytes;
|
|
368033
|
+
},
|
|
368034
|
+
meta: { store }
|
|
368035
|
+
});
|
|
368036
|
+
}
|
|
368037
|
+
async function _loadParquetSchemaBytes({ queryClient, store }, parquetPath, partIndex = void 0) {
|
|
368038
|
+
return queryClient.fetchQuery({
|
|
368039
|
+
queryKey: ["SpatialDataTableSource", "_loadParquetSchemaBytes", parquetPath, partIndex],
|
|
368040
|
+
staleTime: Infinity,
|
|
368041
|
+
queryFn: async (ctx) => {
|
|
368042
|
+
const store2 = ctx.meta?.store;
|
|
368043
|
+
if (store2.getRange) {
|
|
368044
|
+
const TAIL_LENGTH = 8;
|
|
368045
|
+
let partZeroPath = parquetPath;
|
|
368046
|
+
let tailBytes = await store2.getRange(`/${partZeroPath}`, {
|
|
368047
|
+
suffixLength: TAIL_LENGTH
|
|
368048
|
+
});
|
|
368049
|
+
if (!tailBytes) {
|
|
368050
|
+
partZeroPath = `${parquetPath}/part.${partIndex ?? 0}.parquet`;
|
|
368051
|
+
tailBytes = await store2.getRange(`/${partZeroPath}`, {
|
|
368052
|
+
suffixLength: TAIL_LENGTH
|
|
368053
|
+
});
|
|
368054
|
+
}
|
|
368055
|
+
if (!tailBytes || tailBytes.length < TAIL_LENGTH) {
|
|
368056
|
+
throw new Error(`Failed to load parquet footerLength for ${partZeroPath}`);
|
|
368057
|
+
}
|
|
368058
|
+
const footerLength = new DataView(tailBytes.buffer).getInt32(0, true);
|
|
368059
|
+
const magic = new TextDecoder().decode(tailBytes.slice(4, 8));
|
|
368060
|
+
if (magic !== "PAR1") {
|
|
368061
|
+
throw new Error("Invalid Parquet file: missing PAR1 magic number");
|
|
368062
|
+
}
|
|
368063
|
+
const footerBytes = await store2.getRange(`/${partZeroPath}`, {
|
|
368064
|
+
suffixLength: footerLength + TAIL_LENGTH
|
|
368065
|
+
});
|
|
368066
|
+
if (!footerBytes || footerBytes.length !== footerLength + TAIL_LENGTH) {
|
|
368067
|
+
throw new Error(`Failed to load parquet footer bytes for ${parquetPath}`);
|
|
368068
|
+
}
|
|
368069
|
+
return footerBytes;
|
|
368070
|
+
}
|
|
368071
|
+
return null;
|
|
368072
|
+
},
|
|
368073
|
+
meta: { queryClient, store }
|
|
368074
|
+
});
|
|
368075
|
+
}
|
|
368076
|
+
async function _loadParquetMetadataByPart({ queryClient, store }, parquetPath) {
|
|
368077
|
+
return queryClient.fetchQuery({
|
|
368078
|
+
queryKey: ["SpatialDataTableSource", "_loadParquetMetadataByPart", parquetPath],
|
|
368079
|
+
staleTime: Infinity,
|
|
368080
|
+
queryFn: async (ctx) => {
|
|
368081
|
+
const queryClient2 = (
|
|
368082
|
+
/** @type {QueryClient} */
|
|
368083
|
+
ctx.meta?.queryClient
|
|
368084
|
+
);
|
|
368085
|
+
const { readSchema, readMetadata } = await _getParquetModule({ queryClient: queryClient2 });
|
|
368086
|
+
let partIndex = 0;
|
|
368087
|
+
let numParts;
|
|
368088
|
+
const allMetadata = [];
|
|
368089
|
+
do {
|
|
368090
|
+
try {
|
|
368091
|
+
const schemaBytes = await _loadParquetSchemaBytes({ queryClient: queryClient2, store }, parquetPath, partIndex);
|
|
368092
|
+
if (schemaBytes) {
|
|
368093
|
+
const wasmSchema = readSchema(schemaBytes);
|
|
368094
|
+
const arrowTableForSchema = tableFromIPC(wasmSchema.intoIPCStream());
|
|
368095
|
+
const partMetadata = readMetadata(schemaBytes);
|
|
368096
|
+
const partInfo = {
|
|
368097
|
+
schema: arrowTableForSchema,
|
|
368098
|
+
schemaBytes,
|
|
368099
|
+
metadata: partMetadata
|
|
368100
|
+
};
|
|
368101
|
+
allMetadata.push(partInfo);
|
|
368102
|
+
partIndex += 1;
|
|
368103
|
+
}
|
|
368104
|
+
} catch (error2) {
|
|
368105
|
+
if (error2.message.includes("Failed to load parquet footerLength")) {
|
|
368106
|
+
numParts = partIndex;
|
|
368107
|
+
}
|
|
368108
|
+
}
|
|
368109
|
+
} while (numParts === void 0);
|
|
368110
|
+
const metadata2 = {
|
|
368111
|
+
numRows: 0,
|
|
368112
|
+
numRowGroups: 0,
|
|
368113
|
+
numRowsPerGroup: 0,
|
|
368114
|
+
schema: null
|
|
368115
|
+
};
|
|
368116
|
+
if (allMetadata.length > 0) {
|
|
368117
|
+
const firstPart = allMetadata[0];
|
|
368118
|
+
metadata2.numRows = allMetadata.reduce((sum2, part) => sum2 + part.metadata.fileMetadata().numRows(), 0);
|
|
368119
|
+
metadata2.numRowGroups = allMetadata.reduce((sum2, part) => sum2 + part.metadata.numRowGroups(), 0);
|
|
368120
|
+
metadata2.numRowsPerGroup = firstPart.metadata.rowGroup(0).numRows();
|
|
368121
|
+
metadata2.schema = firstPart.schema.schema;
|
|
368122
|
+
}
|
|
368123
|
+
const result = {
|
|
368124
|
+
...metadata2,
|
|
368125
|
+
// TODO: extract metadata per part and rowGroup into plain objects that match the hyparquet parquetMetadata() return value?
|
|
368126
|
+
// This will also make it easier to test.
|
|
368127
|
+
parts: allMetadata
|
|
368128
|
+
};
|
|
368129
|
+
return result;
|
|
368130
|
+
},
|
|
368131
|
+
meta: { queryClient }
|
|
368132
|
+
});
|
|
368133
|
+
}
|
|
368134
|
+
async function _loadParquetRowGroupByGroupIndex({ queryClient, store }, parquetPath, rowGroupIndex) {
|
|
368135
|
+
return queryClient.fetchQuery({
|
|
368136
|
+
queryKey: ["SpatialDataTableSource", "_loadParquetRowGroupByGroupIndex", parquetPath, rowGroupIndex],
|
|
368137
|
+
staleTime: Infinity,
|
|
368138
|
+
queryFn: async (ctx) => {
|
|
368139
|
+
const queryClient2 = (
|
|
368140
|
+
/** @type {QueryClient} */
|
|
368141
|
+
ctx.meta?.queryClient
|
|
368142
|
+
);
|
|
368143
|
+
const store2 = ctx.meta?.store;
|
|
368144
|
+
const { readParquetRowGroup } = await _getParquetModule({ queryClient: queryClient2 });
|
|
368145
|
+
const allMetadata = await _loadParquetMetadataByPart({ queryClient: queryClient2, store: store2 }, parquetPath);
|
|
368146
|
+
if (rowGroupIndex < 0 || rowGroupIndex >= allMetadata.numRowGroups) {
|
|
368147
|
+
throw new Error(`Row group index ${rowGroupIndex} is out of bounds for parquet table with ${allMetadata.numRowGroups} row groups.`);
|
|
368148
|
+
}
|
|
368149
|
+
let partIndex;
|
|
368150
|
+
let cumulativeRowGroups = 0;
|
|
368151
|
+
for (let i2 = 0; i2 < allMetadata.parts.length; i2++) {
|
|
368152
|
+
const part = allMetadata.parts[i2];
|
|
368153
|
+
const numRowGroupsInPart = part.metadata.numRowGroups();
|
|
368154
|
+
if (rowGroupIndex < cumulativeRowGroups + numRowGroupsInPart) {
|
|
368155
|
+
partIndex = i2;
|
|
368156
|
+
break;
|
|
368157
|
+
}
|
|
368158
|
+
cumulativeRowGroups += numRowGroupsInPart;
|
|
368159
|
+
}
|
|
368160
|
+
if (partIndex === void 0) {
|
|
368161
|
+
throw new Error(`Failed to find part containing row group index ${rowGroupIndex}.`);
|
|
368162
|
+
}
|
|
368163
|
+
const partMetadata = allMetadata.parts[partIndex].metadata;
|
|
368164
|
+
const { schemaBytes } = allMetadata.parts[partIndex];
|
|
368165
|
+
const rowGroupIndexRelativeToPart = rowGroupIndex - cumulativeRowGroups;
|
|
368166
|
+
const rowGroupMetadata = partMetadata.rowGroup(rowGroupIndexRelativeToPart);
|
|
368167
|
+
const rowGroupFileOffset = rowGroupMetadata.fileOffset();
|
|
368168
|
+
const rowGroupCompressedSize = rowGroupMetadata.compressedSize();
|
|
368169
|
+
const rowGroupBytes = await _loadParquetBytes({ queryClient: queryClient2, store: store2 }, parquetPath, { offset: rowGroupFileOffset, length: rowGroupCompressedSize }, partIndex);
|
|
368170
|
+
const rowGroupIPC = readParquetRowGroup(schemaBytes, rowGroupBytes, rowGroupIndexRelativeToPart).intoIPCStream();
|
|
368171
|
+
const rowGroupTable = tableFromIPC(rowGroupIPC);
|
|
368172
|
+
return rowGroupTable;
|
|
368173
|
+
},
|
|
368174
|
+
meta: { queryClient, store }
|
|
368175
|
+
});
|
|
368176
|
+
}
|
|
368177
|
+
async function _loadParquetRowGroupColumnExtent({ queryClient, store }, parquetPath, columnName, rowGroupIndex) {
|
|
368178
|
+
return queryClient.fetchQuery({
|
|
368179
|
+
queryKey: ["SpatialDataTableSource", "_loadParquetRowGroupColumnExtent", parquetPath, columnName, rowGroupIndex],
|
|
368180
|
+
staleTime: Infinity,
|
|
368181
|
+
queryFn: async (ctx) => {
|
|
368182
|
+
const queryClient2 = (
|
|
368183
|
+
/** @type {QueryClient} */
|
|
368184
|
+
ctx.meta?.queryClient
|
|
368185
|
+
);
|
|
368186
|
+
const store2 = ctx.meta?.store;
|
|
368187
|
+
const rowGroupTable = await _loadParquetRowGroupByGroupIndex({ queryClient: queryClient2, store: store2 }, parquetPath, rowGroupIndex);
|
|
368188
|
+
const column2 = rowGroupTable.getChild(columnName);
|
|
368189
|
+
if (!column2) {
|
|
368190
|
+
throw new Error(`Column ${columnName} not found in row group ${rowGroupIndex} of parquet table at ${parquetPath}.`);
|
|
368191
|
+
}
|
|
368192
|
+
if (column2.length === 0) {
|
|
368193
|
+
return { min: null, max: null };
|
|
368194
|
+
}
|
|
368195
|
+
return { min: column2.get(0), max: column2.get(column2.length - 1) };
|
|
368196
|
+
},
|
|
368197
|
+
meta: { queryClient, store }
|
|
368198
|
+
});
|
|
368199
|
+
}
|
|
368200
|
+
function getCachedInRangeSync(queryClient, parquetPath, columnName, lo, hi) {
|
|
368201
|
+
const queryCache = queryClient.getQueryCache();
|
|
368202
|
+
const prevQueries = queryCache.findAll({
|
|
368203
|
+
// Note: Must (manually) keep in sync with queryKey used in _loadParquetRowGroupColumnExtent.
|
|
368204
|
+
queryKey: ["SpatialDataTableSource", "_loadParquetRowGroupColumnExtent", parquetPath, columnName],
|
|
368205
|
+
exact: false
|
|
368206
|
+
});
|
|
368207
|
+
const cachedRowGroupInfo = prevQueries.map((q) => {
|
|
368208
|
+
if (!(q.state.status === "success" && !q.state.isInvalidated)) {
|
|
368209
|
+
return null;
|
|
368210
|
+
}
|
|
368211
|
+
return {
|
|
368212
|
+
queryKey: q.queryKey,
|
|
368213
|
+
index: q.queryKey[4],
|
|
368214
|
+
status: q.state.status,
|
|
368215
|
+
min: q.state.data?.min,
|
|
368216
|
+
max: q.state.data?.max
|
|
368217
|
+
};
|
|
368218
|
+
}).filter((v) => v !== null).toSorted((a2, b2) => a2.index - b2.index);
|
|
368219
|
+
return cachedRowGroupInfo.filter((c2) => c2.index >= lo && c2.index < hi);
|
|
368220
|
+
}
|
|
368221
|
+
async function getCachedInRange(queryClient, parquetPath, columnName, lo, hi) {
|
|
368222
|
+
const queryCache = queryClient.getQueryCache();
|
|
368223
|
+
const prevQueries = queryCache.findAll({
|
|
368224
|
+
// Note: Must (manually) keep in sync with queryKey used in _loadParquetRowGroupColumnExtent.
|
|
368225
|
+
queryKey: ["SpatialDataTableSource", "_loadParquetRowGroupColumnExtent", parquetPath, columnName],
|
|
368226
|
+
exact: false
|
|
368227
|
+
});
|
|
368228
|
+
const cachedRowGroupInfo = prevQueries.map((q) => ({
|
|
368229
|
+
queryKey: q.queryKey,
|
|
368230
|
+
index: q.queryKey[4],
|
|
368231
|
+
status: q.state.status,
|
|
368232
|
+
min: q.state.data?.min,
|
|
368233
|
+
max: q.state.data?.max
|
|
368234
|
+
})).filter((v) => v !== null).toSorted((a2, b2) => a2.index - b2.index);
|
|
368235
|
+
const cachedInRange = cachedRowGroupInfo.filter((c2) => c2.index >= lo && c2.index < hi);
|
|
368236
|
+
const pendingQueries = cachedInRange.filter((c2) => c2.status !== "success");
|
|
368237
|
+
if (pendingQueries.length === 0) {
|
|
368238
|
+
return cachedInRange;
|
|
368239
|
+
}
|
|
368240
|
+
const pendingPromises = pendingQueries.map((c2) => queryClient.ensureQueryData({
|
|
368241
|
+
queryKey: c2.queryKey
|
|
368242
|
+
}));
|
|
368243
|
+
await Promise.all(pendingPromises);
|
|
368244
|
+
return getCachedInRangeSync(queryClient, parquetPath, columnName, lo, hi);
|
|
368245
|
+
}
|
|
368246
|
+
async function _bisectRowGroupsRight({ queryClient, store }, parquetPath, columnName, targetValue) {
|
|
368247
|
+
return queryClient.fetchQuery({
|
|
368248
|
+
queryKey: ["SpatialDataTableSource", "_bisectRowGroupsRight", parquetPath, columnName, targetValue],
|
|
368249
|
+
staleTime: Infinity,
|
|
368250
|
+
queryFn: async (ctx) => {
|
|
368251
|
+
const queryClient2 = (
|
|
368252
|
+
/** @type {QueryClient} */
|
|
368253
|
+
ctx.meta?.queryClient
|
|
368254
|
+
);
|
|
368255
|
+
const store2 = ctx.meta?.store;
|
|
368256
|
+
const allMetadata = await _loadParquetMetadataByPart({ queryClient: queryClient2, store: store2 }, parquetPath);
|
|
368257
|
+
const { numRowGroups } = allMetadata;
|
|
368258
|
+
let lo = 0;
|
|
368259
|
+
let hi = numRowGroups;
|
|
368260
|
+
while (lo < hi) {
|
|
368261
|
+
const cachedInRange = await getCachedInRange(queryClient2, parquetPath, columnName, lo, hi);
|
|
368262
|
+
const betterLo = cachedInRange.slice().reverse().find((c2) => c2.index > lo && targetValue >= c2.max);
|
|
368263
|
+
if (betterLo) {
|
|
368264
|
+
lo = Math.min(hi, betterLo.index + 1);
|
|
368265
|
+
}
|
|
368266
|
+
const betterHi = cachedInRange.find((c2) => targetValue < c2.min);
|
|
368267
|
+
if (betterHi) {
|
|
368268
|
+
hi = Math.max(lo, betterHi.index - 1);
|
|
368269
|
+
}
|
|
368270
|
+
if (lo >= hi) {
|
|
368271
|
+
break;
|
|
368272
|
+
}
|
|
368273
|
+
const mid = Math.floor((lo + hi) / 2);
|
|
368274
|
+
const { max: midVal } = await _loadParquetRowGroupColumnExtent({ queryClient: queryClient2, store: store2 }, parquetPath, columnName, mid);
|
|
368275
|
+
if (midVal === null || targetValue <= midVal) {
|
|
368276
|
+
hi = mid;
|
|
368277
|
+
} else {
|
|
368278
|
+
lo = mid + 1;
|
|
368279
|
+
}
|
|
368280
|
+
}
|
|
368281
|
+
return lo;
|
|
368282
|
+
},
|
|
368283
|
+
meta: { queryClient, store }
|
|
368284
|
+
});
|
|
368285
|
+
}
|
|
368286
|
+
async function _rectToRowGroupIndices({ queryClient, store }, parquetPath, tileBbox, allPointsBbox) {
|
|
368287
|
+
return queryClient.fetchQuery({
|
|
368288
|
+
queryKey: ["SpatialDataTableSource", "_rectToRowGroupIndices", parquetPath, tileBbox, allPointsBbox],
|
|
368289
|
+
staleTime: Infinity,
|
|
368290
|
+
queryFn: async (ctx) => {
|
|
368291
|
+
const queryClient2 = (
|
|
368292
|
+
/** @type {QueryClient} */
|
|
368293
|
+
ctx.meta?.queryClient
|
|
368294
|
+
);
|
|
368295
|
+
const store2 = ctx.meta?.store;
|
|
368296
|
+
const mortonIntervals = sdataMortonQueryRectAux(allPointsBbox, [
|
|
368297
|
+
[tileBbox.left, tileBbox.top],
|
|
368298
|
+
// TODO: is this backwards (bottom/top)?
|
|
368299
|
+
[tileBbox.right, tileBbox.bottom]
|
|
368300
|
+
]);
|
|
368301
|
+
let coveredRowGroupIndices = [];
|
|
368302
|
+
const intervalsSpanMultipleRowGroups = async (startIndex, endIndex) => {
|
|
368303
|
+
if (startIndex > endIndex) {
|
|
368304
|
+
return [false, null];
|
|
368305
|
+
}
|
|
368306
|
+
const [startMin, startMax] = mortonIntervals[startIndex];
|
|
368307
|
+
const [endMin, endMax] = mortonIntervals[endIndex];
|
|
368308
|
+
const [rowGroupIndexMin, rowGroupIndexMax] = await Promise.all([
|
|
368309
|
+
_bisectRowGroupsRight({ queryClient: queryClient2, store: store2 }, parquetPath, "morton_code_2d", startMin),
|
|
368310
|
+
_bisectRowGroupsRight({ queryClient: queryClient2, store: store2 }, parquetPath, "morton_code_2d", endMax)
|
|
368311
|
+
]);
|
|
368312
|
+
if (rowGroupIndexMin === rowGroupIndexMax) {
|
|
368313
|
+
return [false, [rowGroupIndexMin]];
|
|
368314
|
+
}
|
|
368315
|
+
if (rowGroupIndexMin + 1 === rowGroupIndexMax || rowGroupIndexMin - 1 === rowGroupIndexMax) {
|
|
368316
|
+
return [false, [rowGroupIndexMin, rowGroupIndexMax]];
|
|
368317
|
+
}
|
|
368318
|
+
return [true, null];
|
|
368319
|
+
};
|
|
368320
|
+
const intervalIndicesToCheck = [[0, mortonIntervals.length - 1]];
|
|
368321
|
+
while (intervalIndicesToCheck.length > 0) {
|
|
368322
|
+
const [startIndex, endIndex] = intervalIndicesToCheck.pop();
|
|
368323
|
+
const [spansMultipleRowGroups, rowGroupIndices] = await intervalsSpanMultipleRowGroups(startIndex, endIndex);
|
|
368324
|
+
if (!spansMultipleRowGroups) {
|
|
368325
|
+
if (rowGroupIndices !== null) {
|
|
368326
|
+
coveredRowGroupIndices = coveredRowGroupIndices.concat(rowGroupIndices);
|
|
368327
|
+
}
|
|
368328
|
+
} else {
|
|
368329
|
+
if (startIndex === endIndex) {
|
|
368330
|
+
const [intervalMin, intervalMax] = mortonIntervals[startIndex];
|
|
368331
|
+
const [rowGroupIndexMin, rowGroupIndexMax] = await Promise.all([
|
|
368332
|
+
_bisectRowGroupsRight({ queryClient: queryClient2, store: store2 }, parquetPath, "morton_code_2d", intervalMin),
|
|
368333
|
+
_bisectRowGroupsRight({ queryClient: queryClient2, store: store2 }, parquetPath, "morton_code_2d", intervalMax)
|
|
368334
|
+
]);
|
|
368335
|
+
if (rowGroupIndexMin <= rowGroupIndexMax) {
|
|
368336
|
+
coveredRowGroupIndices = coveredRowGroupIndices.concat(range$e(rowGroupIndexMin, rowGroupIndexMax + 1));
|
|
368337
|
+
} else {
|
|
368338
|
+
coveredRowGroupIndices = coveredRowGroupIndices.concat(range$e(rowGroupIndexMax, rowGroupIndexMin + 1));
|
|
368339
|
+
}
|
|
368340
|
+
} else {
|
|
368341
|
+
const midIndex = Math.floor((startIndex + endIndex) / 2);
|
|
368342
|
+
intervalIndicesToCheck.push([startIndex, midIndex]);
|
|
368343
|
+
intervalIndicesToCheck.push([midIndex + 1, endIndex]);
|
|
368344
|
+
}
|
|
368345
|
+
}
|
|
368346
|
+
}
|
|
368347
|
+
const uniqueCoveredRowGroupIndices = Array.from(new Set(coveredRowGroupIndices));
|
|
368348
|
+
return uniqueCoveredRowGroupIndices;
|
|
368349
|
+
},
|
|
368350
|
+
meta: { queryClient, store }
|
|
368351
|
+
});
|
|
367366
368352
|
}
|
|
367367
368353
|
function tableToIndexColumnName(arrowTable) {
|
|
367368
368354
|
const pandasMetadata = arrowTable.schema.metadata.get("pandas");
|
|
@@ -367416,14 +368402,17 @@ function getVarPath(arrPath) {
|
|
|
367416
368402
|
class SpatialDataTableSource extends AnnDataSource {
|
|
367417
368403
|
/**
|
|
367418
368404
|
*
|
|
367419
|
-
* @param {DataSourceParams} params
|
|
368405
|
+
* @param {DataSourceParams & { queryClient: QueryClient }} params
|
|
367420
368406
|
*/
|
|
367421
368407
|
constructor(params2) {
|
|
367422
368408
|
super(params2);
|
|
368409
|
+
const { queryClient } = params2;
|
|
368410
|
+
this.queryClient = queryClient;
|
|
367423
368411
|
this.parquetModulePromise = getParquetModule();
|
|
367424
368412
|
this.rootAttrs = null;
|
|
367425
368413
|
this.elementAttrs = {};
|
|
367426
368414
|
this.parquetTableBytes = {};
|
|
368415
|
+
this.parquetTableIsDirectory = {};
|
|
367427
368416
|
this.obsIndices = {};
|
|
367428
368417
|
this.varIndices = {};
|
|
367429
368418
|
this.varAliases = {};
|
|
@@ -367477,17 +368466,19 @@ class SpatialDataTableSource extends AnnDataSource {
|
|
|
367477
368466
|
* relative to the store root.
|
|
367478
368467
|
* @returns {Promise<Uint8Array|undefined>} The parquet file bytes.
|
|
367479
368468
|
*/
|
|
367480
|
-
async loadParquetBytes(parquetPath) {
|
|
367481
|
-
|
|
367482
|
-
|
|
368469
|
+
async loadParquetBytes(parquetPath, offset2 = void 0, length2 = void 0, partIndex = void 0) {
|
|
368470
|
+
const { store } = this.storeRoot;
|
|
368471
|
+
let getter2 = (path2) => store.get(path2);
|
|
368472
|
+
if (offset2 !== void 0 && length2 !== void 0 && store.getRange) {
|
|
368473
|
+
getter2 = (path2) => store.getRange(path2, {
|
|
368474
|
+
offset: offset2,
|
|
368475
|
+
length: length2
|
|
368476
|
+
});
|
|
367483
368477
|
}
|
|
367484
|
-
let parquetBytes = await
|
|
368478
|
+
let parquetBytes = await getter2(`/${parquetPath}`);
|
|
367485
368479
|
if (!parquetBytes) {
|
|
367486
|
-
const part0Path = `${parquetPath}/part
|
|
367487
|
-
parquetBytes = await
|
|
367488
|
-
}
|
|
367489
|
-
if (parquetBytes) {
|
|
367490
|
-
this.parquetTableBytes[parquetPath] = parquetBytes;
|
|
368480
|
+
const part0Path = `${parquetPath}/part.${partIndex ?? 0}.parquet`;
|
|
368481
|
+
parquetBytes = await getter2(`/${part0Path}`);
|
|
367491
368482
|
}
|
|
367492
368483
|
return parquetBytes;
|
|
367493
368484
|
}
|
|
@@ -367506,7 +368497,7 @@ class SpatialDataTableSource extends AnnDataSource {
|
|
|
367506
368497
|
* @returns {Promise<Uint8Array|null>} The parquet file bytes,
|
|
367507
368498
|
* or null if the store does not support getRange.
|
|
367508
368499
|
*/
|
|
367509
|
-
async loadParquetSchemaBytes(parquetPath) {
|
|
368500
|
+
async loadParquetSchemaBytes(parquetPath, partIndex = void 0) {
|
|
367510
368501
|
const { store } = this.storeRoot;
|
|
367511
368502
|
if (store.getRange) {
|
|
367512
368503
|
const TAIL_LENGTH = 8;
|
|
@@ -367514,12 +368505,10 @@ class SpatialDataTableSource extends AnnDataSource {
|
|
|
367514
368505
|
let tailBytes = await store.getRange(`/${partZeroPath}`, {
|
|
367515
368506
|
suffixLength: TAIL_LENGTH
|
|
367516
368507
|
});
|
|
367517
|
-
|
|
367518
|
-
|
|
367519
|
-
|
|
367520
|
-
|
|
367521
|
-
});
|
|
367522
|
-
}
|
|
368508
|
+
partZeroPath = `${parquetPath}/part.${partIndex ?? 0}.parquet`;
|
|
368509
|
+
tailBytes = await store.getRange(`/${partZeroPath}`, {
|
|
368510
|
+
suffixLength: TAIL_LENGTH
|
|
368511
|
+
});
|
|
367523
368512
|
if (!tailBytes || tailBytes.length < TAIL_LENGTH) {
|
|
367524
368513
|
throw new Error(`Failed to load parquet footerLength for ${parquetPath}`);
|
|
367525
368514
|
}
|
|
@@ -367581,7 +368570,7 @@ class SpatialDataTableSource extends AnnDataSource {
|
|
|
367581
368570
|
const schemaBytes = await this.loadParquetSchemaBytes(parquetPath);
|
|
367582
368571
|
if (schemaBytes) {
|
|
367583
368572
|
const wasmSchema = readSchema(schemaBytes);
|
|
367584
|
-
const arrowTableForSchema =
|
|
368573
|
+
const arrowTableForSchema = tableFromIPC(wasmSchema.intoIPCStream());
|
|
367585
368574
|
indexColumnName = tableToIndexColumnName(arrowTableForSchema);
|
|
367586
368575
|
}
|
|
367587
368576
|
} catch (e3) {
|
|
@@ -367597,14 +368586,14 @@ class SpatialDataTableSource extends AnnDataSource {
|
|
|
367597
368586
|
}
|
|
367598
368587
|
if (columns2 && !indexColumnName) {
|
|
367599
368588
|
const wasmSchema = readSchema(parquetBytes);
|
|
367600
|
-
const arrowTableForSchema =
|
|
368589
|
+
const arrowTableForSchema = tableFromIPC(wasmSchema.intoIPCStream());
|
|
367601
368590
|
indexColumnName = tableToIndexColumnName(arrowTableForSchema);
|
|
367602
368591
|
}
|
|
367603
368592
|
if (options.columns && indexColumnName) {
|
|
367604
368593
|
options.columns = [...options.columns, indexColumnName];
|
|
367605
368594
|
}
|
|
367606
368595
|
const wasmTable = readParquet(parquetBytes, options);
|
|
367607
|
-
const arrowTable =
|
|
368596
|
+
const arrowTable = tableFromIPC(wasmTable.intoIPCStream());
|
|
367608
368597
|
return arrowTable;
|
|
367609
368598
|
}
|
|
367610
368599
|
// TABLE-SPECIFIC METHODS
|
|
@@ -367668,6 +368657,93 @@ class SpatialDataTableSource extends AnnDataSource {
|
|
|
367668
368657
|
this.varAliases[varPath] = this.varAliases[varPath].map((val, ind) => val ? val.concat(` (${index2[ind]})`) : index2[ind]);
|
|
367669
368658
|
return this.varAliases[varPath];
|
|
367670
368659
|
}
|
|
368660
|
+
async _supportsTiledPoints(parquetPath) {
|
|
368661
|
+
const { queryClient } = this;
|
|
368662
|
+
const { store } = this.storeRoot;
|
|
368663
|
+
const allMetadata = await _loadParquetMetadataByPart({ queryClient, store }, parquetPath);
|
|
368664
|
+
const { numRowsPerGroup } = allMetadata;
|
|
368665
|
+
const numRowsTotal = allMetadata.numRows;
|
|
368666
|
+
if (numRowsPerGroup >= 1e5) {
|
|
368667
|
+
if (numRowsTotal > 5e6) {
|
|
368668
|
+
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.`);
|
|
368669
|
+
}
|
|
368670
|
+
return false;
|
|
368671
|
+
}
|
|
368672
|
+
const requiredColumns = ["x", "y", "feature_index", "morton_code_2d"];
|
|
368673
|
+
const hasColumns = allMetadata?.schema?.fields?.map((f2) => f2.name);
|
|
368674
|
+
if (!hasColumns) {
|
|
368675
|
+
return false;
|
|
368676
|
+
}
|
|
368677
|
+
const hasRequiredColumns = requiredColumns.every((col) => hasColumns.includes(col));
|
|
368678
|
+
if (!hasRequiredColumns && numRowsTotal > 5e6) {
|
|
368679
|
+
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.`);
|
|
368680
|
+
}
|
|
368681
|
+
return hasRequiredColumns;
|
|
368682
|
+
}
|
|
368683
|
+
/**
|
|
368684
|
+
* Load point data using a tiled approach.
|
|
368685
|
+
* @param {string} parquetPath A path to a parquet file (or directory).
|
|
368686
|
+
* @param {{ left: number, top: number, right: number, bottom: number }} tileBbox
|
|
368687
|
+
* @param {{ x_min: number, y_min: number, x_max: number, y_max: number }} allPointsBbox
|
|
368688
|
+
* @param {string[]|undefined} columns An optional list of column names to load.
|
|
368689
|
+
* @returns
|
|
368690
|
+
*/
|
|
368691
|
+
async loadParquetTableInRect(parquetPath, tileBbox, allPointsBbox, signal) {
|
|
368692
|
+
const { queryClient } = this;
|
|
368693
|
+
const { store } = this.storeRoot;
|
|
368694
|
+
const TILE_SIZE2 = 256;
|
|
368695
|
+
let tileBboxes = [];
|
|
368696
|
+
if (tileBbox.right - tileBbox.left > TILE_SIZE2 || tileBbox.bottom - tileBbox.top > TILE_SIZE2) {
|
|
368697
|
+
const xSteps = Math.ceil((tileBbox.right - tileBbox.left) / TILE_SIZE2);
|
|
368698
|
+
const ySteps = Math.ceil((tileBbox.bottom - tileBbox.top) / TILE_SIZE2);
|
|
368699
|
+
const xStepSize = (tileBbox.right - tileBbox.left) / xSteps;
|
|
368700
|
+
const yStepSize = (tileBbox.bottom - tileBbox.top) / ySteps;
|
|
368701
|
+
for (let i2 = 0; i2 < xSteps; i2++) {
|
|
368702
|
+
for (let j = 0; j < ySteps; j++) {
|
|
368703
|
+
const subTileBbox = {
|
|
368704
|
+
left: tileBbox.left + i2 * xStepSize,
|
|
368705
|
+
right: Math.min(tileBbox.left + (i2 + 1) * xStepSize, tileBbox.right),
|
|
368706
|
+
top: tileBbox.top + j * yStepSize,
|
|
368707
|
+
bottom: Math.min(tileBbox.top + (j + 1) * yStepSize, tileBbox.bottom)
|
|
368708
|
+
};
|
|
368709
|
+
tileBboxes.push(subTileBbox);
|
|
368710
|
+
}
|
|
368711
|
+
}
|
|
368712
|
+
} else {
|
|
368713
|
+
tileBboxes = [tileBbox];
|
|
368714
|
+
}
|
|
368715
|
+
const rowGroupIndicesPerTile = await Promise.all(tileBboxes.map(async (subTileBbox) => _rectToRowGroupIndices({ queryClient, store }, parquetPath, subTileBbox, allPointsBbox)));
|
|
368716
|
+
const uniqueCoveredRowGroupIndices = Array.from(new Set(rowGroupIndicesPerTile.flat())).toSorted((a2, b2) => a2 - b2);
|
|
368717
|
+
const allMetadata = await _loadParquetMetadataByPart({ queryClient, store }, parquetPath);
|
|
368718
|
+
const { numRowsPerGroup } = allMetadata;
|
|
368719
|
+
const numRowGroups = uniqueCoveredRowGroupIndices.length;
|
|
368720
|
+
const totalNumRows = numRowsPerGroup * numRowGroups;
|
|
368721
|
+
const xArr = new Float32Array(totalNumRows);
|
|
368722
|
+
const yArr = new Float32Array(totalNumRows);
|
|
368723
|
+
const featureIndexArr = new Uint32Array(totalNumRows);
|
|
368724
|
+
const rowGroupTables = await Promise.all(uniqueCoveredRowGroupIndices.map(async (rowGroupIndex) => _loadParquetRowGroupByGroupIndex({ queryClient, store }, parquetPath, rowGroupIndex)));
|
|
368725
|
+
let rowOffset = 0;
|
|
368726
|
+
rowGroupTables.forEach((table2) => {
|
|
368727
|
+
const xColumn = table2.getChild("x");
|
|
368728
|
+
const yColumn = table2.getChild("y");
|
|
368729
|
+
const featureIndexColumn = table2.getChild("feature_index");
|
|
368730
|
+
if (!xColumn || !yColumn || !featureIndexColumn) {
|
|
368731
|
+
throw new Error(`Missing required column in parquet table at ${parquetPath}. Required columns: x, y, feature_index`);
|
|
368732
|
+
}
|
|
368733
|
+
xArr.set(xColumn.toArray(), rowOffset);
|
|
368734
|
+
yArr.set(yColumn.toArray(), rowOffset);
|
|
368735
|
+
featureIndexArr.set(featureIndexColumn.toArray(), rowOffset);
|
|
368736
|
+
rowOffset += numRowsPerGroup;
|
|
368737
|
+
});
|
|
368738
|
+
return {
|
|
368739
|
+
data: {
|
|
368740
|
+
x: xArr,
|
|
368741
|
+
y: yArr,
|
|
368742
|
+
featureIndices: featureIndexArr
|
|
368743
|
+
},
|
|
368744
|
+
shape: [3, totalNumRows]
|
|
368745
|
+
};
|
|
368746
|
+
}
|
|
367671
368747
|
}
|
|
367672
368748
|
class BaseEvent {
|
|
367673
368749
|
/**
|
|
@@ -373823,6 +374899,33 @@ class SpatialDataPointsSource extends SpatialDataTableSource {
|
|
|
373823
374899
|
data: axisColumnArrs
|
|
373824
374900
|
};
|
|
373825
374901
|
}
|
|
374902
|
+
/**
|
|
374903
|
+
*
|
|
374904
|
+
* @param {string} elementPath
|
|
374905
|
+
* @param {{ left: number, top: number, right: number, bottom: number }} tileBbox
|
|
374906
|
+
* @returns {Promise<{
|
|
374907
|
+
* data: [ZarrTypedArray<any>, ZarrTypedArray<any>],
|
|
374908
|
+
* shape: [number, number],
|
|
374909
|
+
* }>} A promise for a zarr array containing the data.
|
|
374910
|
+
*/
|
|
374911
|
+
async loadPointsInRect(elementPath, tileBbox, signal) {
|
|
374912
|
+
const parquetPath = getParquetPath(elementPath);
|
|
374913
|
+
const zattrs = await this.loadSpatialDataElementAttrs(elementPath);
|
|
374914
|
+
const {
|
|
374915
|
+
// axes,
|
|
374916
|
+
// spatialdata_attrs: spatialDataAttrs,
|
|
374917
|
+
// The bounding box (extent) of all points.
|
|
374918
|
+
// Required for un-normalization from uints back to floats.
|
|
374919
|
+
// TODO: decide whether these will be stored here or somewhere else.
|
|
374920
|
+
// Reference: https://github.com/vitessce/vitessce-python/pull/476#issuecomment-3362656956
|
|
374921
|
+
bounding_box: allPointsBbox
|
|
374922
|
+
} = zattrs;
|
|
374923
|
+
return this.loadParquetTableInRect(parquetPath, tileBbox, allPointsBbox, signal);
|
|
374924
|
+
}
|
|
374925
|
+
async supportsLoadPointsInRect(elementPath) {
|
|
374926
|
+
const parquetPath = getParquetPath(elementPath);
|
|
374927
|
+
return this._supportsTiledPoints(parquetPath);
|
|
374928
|
+
}
|
|
373826
374929
|
}
|
|
373827
374930
|
class OmeTiffSource {
|
|
373828
374931
|
constructor({ url, requestInit: requestInit2 }) {
|
|
@@ -379967,10 +381070,27 @@ const baseCoordinationTypes = [
|
|
|
379967
381070
|
color: rgbArray
|
|
379968
381071
|
})).nullable()
|
|
379969
381072
|
),
|
|
381073
|
+
new PluginCoordinationType(
|
|
381074
|
+
CoordinationType$1.FEATURE_COLOR,
|
|
381075
|
+
null,
|
|
381076
|
+
z.array(z.object({
|
|
381077
|
+
name: z.string(),
|
|
381078
|
+
color: rgbArray
|
|
381079
|
+
})).nullable()
|
|
381080
|
+
),
|
|
379970
381081
|
new PluginCoordinationType(
|
|
379971
381082
|
CoordinationType$1.OBS_COLOR_ENCODING,
|
|
379972
381083
|
"cellSetSelection",
|
|
379973
|
-
z.enum([
|
|
381084
|
+
z.enum([
|
|
381085
|
+
"geneSelection",
|
|
381086
|
+
"cellSetSelection",
|
|
381087
|
+
"spatialChannelColor",
|
|
381088
|
+
"spatialLayerColor",
|
|
381089
|
+
"obsLabels",
|
|
381090
|
+
// For point coloring.
|
|
381091
|
+
"random",
|
|
381092
|
+
"randomByFeature"
|
|
381093
|
+
])
|
|
379974
381094
|
),
|
|
379975
381095
|
new PluginCoordinationType(CoordinationType$1.FEATURE_FILTER, null, z.array(z.string()).nullable()),
|
|
379976
381096
|
new PluginCoordinationType(CoordinationType$1.FEATURE_HIGHLIGHT, null, z.string().nullable()),
|
|
@@ -380001,7 +381121,7 @@ const baseCoordinationTypes = [
|
|
|
380001
381121
|
null,
|
|
380002
381122
|
z.array(obsSetPath).nullable()
|
|
380003
381123
|
),
|
|
380004
|
-
new PluginCoordinationType(CoordinationType$1.FEATURE_FILTER_MODE, null, z.enum(["featureFilter", "featureSetFilter"]).nullable()),
|
|
381124
|
+
new PluginCoordinationType(CoordinationType$1.FEATURE_FILTER_MODE, null, z.enum(["featureFilter", "featureSetFilter", "featureSelection"]).nullable()),
|
|
380005
381125
|
new PluginCoordinationType(
|
|
380006
381126
|
CoordinationType$1.FEATURE_VALUE_TRANSFORM,
|
|
380007
381127
|
null,
|