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