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