UNPKG

vitessce

Version:

Vitessce app and React component library

1,544 lines (1,519 loc) 1.91 MB
var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __pow = Math.pow; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); var __require = typeof require !== "undefined" ? require : (x) => { throw new Error('Dynamic require of "' + x + '" is not supported'); }; var __objRest = (source, exclude) => { var target = {}; for (var prop in source) if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0) target[prop] = source[prop]; if (source != null && __getOwnPropSymbols) for (var prop of __getOwnPropSymbols(source)) { if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop)) target[prop] = source[prop]; } return target; }; var __publicField = (obj, key, value) => { __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); return value; }; var __async = (__this, __arguments, generator) => { return new Promise((resolve, reject) => { var fulfilled = (value) => { try { step(generator.next(value)); } catch (e) { reject(e); } }; var rejected = (value) => { try { step(generator.throw(value)); } catch (e) { reject(e); } }; var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); step((generator = generator.apply(__this, __arguments)).next()); }); }; // src/components/heatmap/HeatmapSubscriber.js import React14, { useEffect as useEffect5, useState as useState6, useCallback as useCallback5, useMemo as useMemo5 } from "react"; // src/components/TitleInfo.js import React3, { useState as useState2 } from "react"; import { makeStyles as makeStyles2 } from "@material-ui/core/styles"; import CloudDownloadIcon from "@material-ui/icons/CloudDownload"; import MenuItem from "@material-ui/core/MenuItem"; import IconButton2 from "@material-ui/core/IconButton"; import Link from "@material-ui/core/Link"; import ArrowDropDownIcon from "@material-ui/icons/ArrowDropDown"; import ArrowDropUpIcon from "@material-ui/icons/ArrowDropUp"; import SettingsIcon from "@material-ui/icons/Settings"; import CloseIcon from "@material-ui/icons/Close"; // src/components/classNames.js var TOOLTIP_ANCESTOR = "tooltip-ancestor"; var CARD = `card card-body my-2 ${TOOLTIP_ANCESTOR}`; var PRIMARY_CARD = `${CARD} bg-primary`; var SECONDARY_CARD = `${CARD} bg-secondary`; var BLACK_CARD = `${CARD} bg-black`; var SCROLL_CARD = `${PRIMARY_CARD} scroll`; var VITESSCE_CONTAINER = "vitessce-container"; // src/components/LoadingIndicator.js import React from "react"; import CircularProgress from "@material-ui/core/CircularProgress"; function LoadingIndicator() { return /* @__PURE__ */ React.createElement("div", { className: "loading-indicator-backdrop" }, /* @__PURE__ */ React.createElement("div", { className: "loading-indicator-container" }, /* @__PURE__ */ React.createElement(CircularProgress, null))); } // src/components/shared-mui/components.js import React2, { useRef as useRef3 } from "react"; import Paper from "@material-ui/core/Paper"; import Popper from "@material-ui/core/Popper"; import IconButton from "@material-ui/core/IconButton"; import MenuList from "@material-ui/core/MenuList"; import ClickAwayListener from "@material-ui/core/ClickAwayListener"; import Fade from "@material-ui/core/Fade"; // src/components/hooks.js import { useRef as useRef2, useState, useEffect, useCallback as useCallback2, useMemo as useMemo2 } from "react"; import debounce from "lodash/debounce"; // src/app/state/hooks.js import { useRef, useCallback, useMemo } from "react"; import create from "zustand"; import createContext from "zustand/context"; import shallow from "zustand/shallow"; // src/app/constants.js var Component = { DESCRIPTION: "description", STATUS: "status", GENES: "genes", CELL_SETS: "cellSets", SCATTERPLOT: "scatterplot", SPATIAL: "spatial", HEATMAP: "heatmap", LAYER_CONTROLLER: "layerController", CELL_SET_SIZES: "cellSetSizes", GENOMIC_PROFILES: "genomicProfiles", CELL_SET_EXPRESSION: "cellSetExpression", EXPRESSION_HISTOGRAM: "expressionHistogram", GATING: "gating" }; var DataType = { CELLS: "cells", CELL_SETS: "cell-sets", EXPRESSION_MATRIX: "expression-matrix", GENOMIC_PROFILES: "genomic-profiles", MOLECULES: "molecules", NEIGHBORHOODS: "neighborhoods", RASTER: "raster" }; var FileType = { CELLS_JSON: "cells.json", CELL_SETS_JSON: "cell-sets.json", EXPRESSION_MATRIX_ZARR: "expression-matrix.zarr", GENOMIC_PROFILES_ZARR: "genomic-profiles.zarr", MOLECULES_JSON: "molecules.json", NEIGHBORHOODS_JSON: "neighborhoods.json", RASTER_JSON: "raster.json", RASTER_OME_ZARR: "raster.ome-zarr", CLUSTERS_JSON: "clusters.json", GENES_JSON: "genes.json", ANNDATA_CELL_SETS_ZARR: "anndata-cell-sets.zarr", ANNDATA_CELLS_ZARR: "anndata-cells.zarr", ANNDATA_EXPRESSION_MATRIX_ZARR: "anndata-expression-matrix.zarr" }; var CoordinationType = { DATASET: "dataset", OBS_TYPE: "obsType", FEATURE_TYPE: "featureType", FEATURE_VALUE_TYPE: "featureValueType", EMBEDDING_TYPE: "embeddingType", EMBEDDING_ZOOM: "embeddingZoom", EMBEDDING_ROTATION: "embeddingRotation", EMBEDDING_TARGET_X: "embeddingTargetX", EMBEDDING_TARGET_Y: "embeddingTargetY", EMBEDDING_TARGET_Z: "embeddingTargetZ", EMBEDDING_OBS_SET_POLYGONS_VISIBLE: "embeddingObsSetPolygonsVisible", EMBEDDING_OBS_SET_LABELS_VISIBLE: "embeddingObsSetLabelsVisible", EMBEDDING_OBS_SET_LABEL_SIZE: "embeddingObsSetLabelSize", EMBEDDING_OBS_RADIUS: "embeddingObsRadius", EMBEDDING_OBS_RADIUS_MODE: "embeddingObsRadiusMode", EMBEDDING_OBS_OPACITY: "embeddingObsOpacity", EMBEDDING_OBS_OPACITY_MODE: "embeddingObsOpacityMode", SPATIAL_ZOOM: "spatialZoom", SPATIAL_ROTATION: "spatialRotation", SPATIAL_TARGET_X: "spatialTargetX", SPATIAL_TARGET_Y: "spatialTargetY", SPATIAL_TARGET_Z: "spatialTargetZ", SPATIAL_ROTATION_X: "spatialRotationX", SPATIAL_ROTATION_Y: "spatialRotationY", SPATIAL_ROTATION_Z: "spatialRotationZ", SPATIAL_ROTATION_ORBIT: "spatialRotationOrbit", SPATIAL_ORBIT_AXIS: "spatialOrbitAxis", SPATIAL_AXIS_FIXED: "spatialAxisFixed", HEATMAP_ZOOM_X: "heatmapZoomX", HEATMAP_ZOOM_Y: "heatmapZoomY", HEATMAP_TARGET_X: "heatmapTargetX", HEATMAP_TARGET_Y: "heatmapTargetY", OBS_FILTER: "obsFilter", OBS_HIGHLIGHT: "obsHighlight", OBS_SET_SELECTION: "obsSetSelection", OBS_SET_HIGHLIGHT: "obsSetHighlight", OBS_SET_COLOR: "obsSetColor", FEATURE_FILTER: "featureFilter", FEATURE_HIGHLIGHT: "featureHighlight", FEATURE_SELECTION: "featureSelection", FEATURE_VALUE_COLORMAP: "featureValueColormap", FEATURE_VALUE_TRANSFORM: "featureValueTransform", FEATURE_VALUE_COLORMAP_RANGE: "featureValueColormapRange", OBS_COLOR_ENCODING: "obsColorEncoding", SPATIAL_IMAGE_LAYER: "spatialImageLayer", SPATIAL_SEGMENTATION_LAYER: "spatialSegmentationLayer", SPATIAL_POINT_LAYER: "spatialPointLayer", SPATIAL_NEIGHBORHOOD_LAYER: "spatialNeighborhoodLayer", GENOMIC_ZOOM_X: "genomicZoomX", GENOMIC_ZOOM_Y: "genomicZoomY", GENOMIC_TARGET_X: "genomicTargetX", GENOMIC_TARGET_Y: "genomicTargetY", ADDITIONAL_OBS_SETS: "additionalObsSets", MOLECULE_HIGHLIGHT: "moleculeHighlight", GATING_FEATURE_SELECTION_X: "gatingFeatureSelectionX", GATING_FEATURE_SELECTION_Y: "gatingFeatureSelectionY", FEATURE_VALUE_TRANSFORM_COEFFICIENT: "featureValueTransformCoefficient" }; // src/utils.js function fromEntries(iterable) { return [...iterable].reduce((obj, { 0: key, 1: val }) => Object.assign(obj, { [key]: val }), {}); } function pluralize(singular, plural, count) { return count === 1 ? singular : plural; } function capitalize(word) { return word.charAt(0).toUpperCase() + word.slice(1); } function getLongestString(strings) { return strings.reduce((prevLongest, currentValue) => prevLongest.length > currentValue.length ? prevLongest : currentValue); } function getNextScope(prevScopes) { const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const nextCharIndices = [0]; function next() { const r = []; nextCharIndices.forEach((charIndex) => { r.unshift(chars[charIndex]); }); let increment = true; for (let i = 0; i < nextCharIndices.length; i++) { const val = ++nextCharIndices[i]; if (val >= chars.length) { nextCharIndices[i] = 0; } else { increment = false; break; } } if (increment) { nextCharIndices.push(0); } return r.join(""); } let nextScope; do { nextScope = next(); } while (prevScopes.includes(nextScope)); return nextScope; } function getSourceFromLoader(loader, level) { const { data } = loader; const source = Array.isArray(data) ? data[level || data.length - 1] : data; return source; } function isRgb(loader) { const source = getSourceFromLoader(loader); const { shape, dtype, labels } = source; const channelSize = shape[labels.indexOf("c")]; return channelSize === 3 && dtype === "Uint8"; } // src/app/state/hooks.js var { Provider: ViewConfigProviderLocal, useStore: useViewConfigStoreLocal, useStoreApi: useViewConfigStoreApiLocal } = createContext(); var ViewConfigProvider = ViewConfigProviderLocal; var useViewConfigStore = useViewConfigStoreLocal; var useViewConfigStoreApi = useViewConfigStoreApiLocal; var { Provider: AuxiliaryProviderLocal, useStore: useAuxiliaryStoreLocal } = createContext(); var AuxiliaryProvider = AuxiliaryProviderLocal; var useAuxiliaryStore = useAuxiliaryStoreLocal; var createViewConfigStore = () => create((set) => ({ viewConfig: null, loaders: null, setViewConfig: (viewConfig) => set({ viewConfig }), setLoaders: (loaders) => set({ loaders }), setCoordinationValue: ({ parameter, scope, value }) => set((state) => ({ viewConfig: __spreadProps(__spreadValues({}, state.viewConfig), { coordinationSpace: __spreadProps(__spreadValues({}, state.viewConfig.coordinationSpace), { [parameter]: __spreadProps(__spreadValues({}, state.viewConfig.coordinationSpace[parameter]), { [scope]: value }) }) }) })), removeComponent: (uid) => set((state) => { const newLayout = state.viewConfig.layout.filter((c) => c.uid !== uid); return { viewConfig: __spreadProps(__spreadValues({}, state.viewConfig), { layout: newLayout }) }; }), changeLayout: (newComponentProps) => set((state) => { const newLayout = state.viewConfig.layout.slice(); newComponentProps.forEach(([i, newProps]) => { newLayout[i] = __spreadValues(__spreadValues({}, newLayout[i]), newProps); }); return { viewConfig: __spreadProps(__spreadValues({}, state.viewConfig), { layout: newLayout }) }; }) })); var useComponentLayout = (component, scopes, coordinationScopes) => useViewConfigStore((state) => state.viewConfig.layout.filter((l) => l.component === component).filter((l) => scopes.every((scope) => l.coordinationScopes[scope] === coordinationScopes[scope]))); var createAuxiliaryStore = () => create((set) => ({ auxiliaryStore: null, setCoordinationValue: ({ parameter, scope, value }) => set((state) => ({ auxiliaryStore: __spreadProps(__spreadValues({}, state.auxiliaryStore), { [parameter]: { [scope]: value } }) })) })); var useHoverStore = create((set) => ({ componentHover: null, setComponentHover: (componentHover) => set({ componentHover }) })); var useWarnStore = create((set) => ({ warning: null, setWarning: (warning) => set({ warning }) })); var useViewInfoStore = create((set) => ({ viewInfo: {}, setComponentViewInfo: (uuid, viewInfo) => set((state) => ({ viewInfo: __spreadProps(__spreadValues({}, state.viewInfo), { [uuid]: viewInfo }) })) })); var useGridSizeStore = create((set) => ({ resizeCount: {}, incrementResizeCount: () => set((state) => ({ resizeCount: state.resizeCount + 1 })) })); function useCoordination(parameters, coordinationScopes) { const setCoordinationValue = useViewConfigStore((state) => state.setCoordinationValue); const values = useViewConfigStore((state) => { const { coordinationSpace } = state.viewConfig; return fromEntries(parameters.map((parameter) => { if (coordinationSpace && coordinationSpace[parameter]) { const value = coordinationSpace[parameter][coordinationScopes[parameter]]; return [parameter, value]; } return [parameter, void 0]; })); }, shallow); const setters = useMemo(() => fromEntries(parameters.map((parameter) => { const setterName = `set${capitalize(parameter)}`; const setterFunc = (value) => setCoordinationValue({ parameter, scope: coordinationScopes[parameter], value }); return [setterName, setterFunc]; })), [parameters, coordinationScopes]); return [values, setters]; } function useDatasetUids(coordinationScopes) { const parameter = CoordinationType.DATASET; const datasetScopes = coordinationScopes[parameter]; const datasetUids = useViewConfigStore((state) => { const { coordinationSpace } = state.viewConfig; const datasetScopesArr = Array.isArray(datasetScopes) ? datasetScopes : [datasetScopes]; return fromEntries(datasetScopesArr.map((datasetScope) => { if (coordinationSpace && coordinationSpace[parameter]) { const value = coordinationSpace[parameter][datasetScope]; return [datasetScope, value]; } return [datasetScope, void 0]; })); }, shallow); return datasetUids; } function useMultiDatasetCoordination(parameters, coordinationScopes) { const setCoordinationValue = useViewConfigStore((state) => state.setCoordinationValue); const datasetScopes = coordinationScopes[CoordinationType.DATASET]; const datasetScopesArr = Array.isArray(datasetScopes) ? datasetScopes : [datasetScopes]; const values = useViewConfigStore((state) => { const { coordinationSpace } = state.viewConfig; return fromEntries(datasetScopesArr.map((datasetScope) => { const datasetValues = fromEntries(parameters.map((parameter) => { if (coordinationSpace && coordinationSpace[parameter]) { let value; const parameterSpace = coordinationSpace[parameter]; const parameterScope = coordinationScopes[parameter]; if (typeof parameterScope === "object") { value = parameterSpace[parameterScope[datasetScope]]; } else if (typeof parameterScope === "string") { value = parameterSpace[parameterScope]; } else { console.error(`coordination scope for ${parameter} must be of type string or object.`); } return [parameter, value]; } return [parameter, void 0]; })); return [datasetScope, datasetValues]; })); }, shallow); const setters = useMemo(() => fromEntries(datasetScopesArr.map((datasetScope) => { const datasetSetters = fromEntries(parameters.map((parameter) => { const setterName = `set${capitalize(parameter)}`; let setterFunc; const parameterScope = coordinationScopes[parameter]; if (typeof parameterScope === "object") { setterFunc = (value) => setCoordinationValue({ parameter, scope: parameterScope[datasetScope], value }); } else if (typeof parameterScope === "string") { setterFunc = (value) => setCoordinationValue({ parameter, scope: parameterScope, value }); } else { console.error(`coordination scope for ${parameter} must be of type string or object.`); } return [setterName, setterFunc]; })); return [datasetScope, datasetSetters]; })), [parameters, coordinationScopes]); return [values, setters]; } var AUXILIARY_COORDINATION_TYPES_MAP = { spatialImageLayer: ["rasterLayersCallbacks", "areLoadingRasterChannnels"] }; var mapCoordinationScopes = (coordinationScopes) => { const newCoordinationScopes = {}; Object.keys(coordinationScopes).forEach((key) => { const newCoordinationTypes = AUXILIARY_COORDINATION_TYPES_MAP[key] || []; newCoordinationTypes.forEach((coordinationType) => { newCoordinationScopes[coordinationType || key] = coordinationScopes[key]; }); }); return newCoordinationScopes; }; var mapParameters = (parameters) => parameters.map((parameter) => AUXILIARY_COORDINATION_TYPES_MAP[parameter]).filter(Boolean).flat(); function useAuxiliaryCoordination(parameters, coordinationScopes) { const setCoordinationValue = useAuxiliaryStore((state) => state.setCoordinationValue); const mappedCoordinationScopes = mapCoordinationScopes(coordinationScopes); const mappedParameters = mapParameters(parameters); const values = useAuxiliaryStore((state) => { const { auxiliaryStore } = state; return fromEntries(mappedParameters.map((parameter) => { if (auxiliaryStore && auxiliaryStore[parameter]) { const value = auxiliaryStore[parameter][mappedCoordinationScopes[parameter]]; return [parameter, value]; } return [parameter, void 0]; })); }, shallow); const setters = useMemo(() => fromEntries(mappedParameters.map((parameter) => { const setterName = `set${capitalize(parameter)}`; const setterFunc = (value) => setCoordinationValue({ parameter, scope: mappedCoordinationScopes[parameter], value }); return [setterName, setterFunc]; })), [parameters, coordinationScopes]); return [values, setters]; } function useLoaders() { return useViewConfigStore((state) => state.loaders); } function useLayout() { return useViewConfigStore((state) => { var _a2; return (_a2 = state.viewConfig) == null ? void 0 : _a2.layout; }); } function useRemoveComponent() { return useViewConfigStore((state) => state.removeComponent); } function useChangeLayout() { return useViewConfigStore((state) => state.changeLayout); } function useSetLoaders() { return useViewConfigStore((state) => state.setLoaders); } function useSetViewConfig(viewConfigStoreApi) { const setViewConfigRef = useRef(viewConfigStoreApi.getState().setViewConfig); const setViewConfig = setViewConfigRef.current; return setViewConfig; } function useComponentHover() { return useHoverStore((state) => state.componentHover); } function useSetComponentHover() { return useHoverStore((state) => state.setComponentHover); } function useWarning() { return useWarnStore((state) => state.warning); } function useSetWarning() { return useWarnStore((state) => state.setWarning); } function useComponentViewInfo(uuid) { return useViewInfoStore(useCallback((state) => state.viewInfo[uuid], [uuid])); } function useSetComponentViewInfo(uuid) { const setViewInfoRef = useRef(useViewInfoStore.getState().setComponentViewInfo); const setComponentViewInfo = (viewInfo) => setViewInfoRef.current(uuid, viewInfo); return setComponentViewInfo; } function useGridResize() { return useGridSizeStore((state) => state.resizeCount); } function useEmitGridResize() { return useGridSizeStore((state) => state.incrementResizeCount); } // src/components/hooks.js function getWindowDimensions() { const { innerWidth: width, innerHeight: height } = window; return { width, height }; } function useVitessceContainer(ref) { return useCallback2(() => { if (ref.current) { return ref.current.closest(`.${VITESSCE_CONTAINER}`); } return null; }, [ref]); } function useWindowDimensions() { const [windowDimensions, setWindowDimensions] = useState(getWindowDimensions()); useEffect(() => { function handleResize() { setWindowDimensions(getWindowDimensions()); } const onResizeDebounced = debounce(handleResize, 100, { trailing: true }); window.addEventListener("resize", onResizeDebounced); return () => window.removeEventListener("resize", onResizeDebounced); }, []); return windowDimensions; } function useGridItemSize() { const containerRef = useRef2(); const [height, setHeight] = useState(); const [width, setWidth] = useState(); const resizeCount = useGridResize(); const incrementResizeCount = useEmitGridResize(); useEffect(() => { function onWindowResize() { incrementResizeCount(); } const onResizeDebounced = debounce(onWindowResize, 100, { trailing: true }); window.addEventListener("resize", onResizeDebounced); onWindowResize(); return () => { window.removeEventListener("resize", onResizeDebounced); }; }, [incrementResizeCount]); useEffect(() => { if (!containerRef.current) return; const container = containerRef.current; const containerRect = container.getBoundingClientRect(); setHeight(containerRect.height); setWidth(containerRect.width); }, [resizeCount]); return [width, height, containerRef]; } function useDeckCanvasSize() { const deckRef = useRef2(); const [height, setHeight] = useState(); const [width, setWidth] = useState(); const resizeCount = useGridResize(); const incrementResizeCount = useEmitGridResize(); useEffect(() => { function onWindowResize() { incrementResizeCount(); } const onResizeDebounced = debounce(onWindowResize, 100, { trailing: true }); window.addEventListener("resize", onResizeDebounced); onWindowResize(); return () => { window.removeEventListener("resize", onResizeDebounced); }; }, [incrementResizeCount]); useEffect(() => { if (!deckRef.current) return; const { canvas } = deckRef.current.deck; const canvasRect = canvas.getBoundingClientRect(); setHeight(canvasRect.height); setWidth(canvasRect.width); }, [resizeCount]); return [width, height, deckRef]; } function useReady(supportedItems) { const items2 = supportedItems; const [waiting, setWaiting] = useState(items2); const setItemIsReady = useCallback2((readyItem) => { setWaiting((waitingItems) => { const nextWaitingItems = waitingItems.filter((item) => item !== readyItem); console.log(`cleared ${readyItem}; waiting on ${nextWaitingItems.length}: ${JSON.stringify(nextWaitingItems)}`); return nextWaitingItems; }); }, [setWaiting]); const setItemIsNotReady = useCallback2((notReadyItem) => { setWaiting((waitingItems) => { const nextWaitingItems = [...waitingItems, notReadyItem]; console.log(`waiting on ${nextWaitingItems.length}: ${JSON.stringify(nextWaitingItems)}`); return nextWaitingItems; }); }, [setWaiting]); const resetReadyItems = useCallback2(() => { setWaiting(items2); console.log(`waiting on ${items2.length}: ${JSON.stringify(items2)}`); }, [setWaiting, items2]); const isReady = waiting.length === 0; return [isReady, setItemIsReady, setItemIsNotReady, resetReadyItems]; } function useUrls() { const [urls, setUrls] = useState([]); const addUrl = useCallback2((url, name2) => { if (url) { setUrls((prev) => [...prev, { url, name: name2 }]); } }, [setUrls]); const resetUrls = useCallback2(() => { setUrls([]); }, [setUrls]); return [urls, addUrl, resetUrls]; } function useClosestVitessceContainerSize(ref) { const [height, setHeight] = useState(); const [width, setWidth] = useState(); useEffect(() => { function onWindowResize() { if (ref.current) { const { clientHeight: componentHeight, clientWidth: componentWidth } = ref.current.closest(".vitessce-container"); setWidth(componentWidth); setHeight(componentHeight); } } const onResizeDebounced = debounce(onWindowResize, 100, { trailing: true }); window.addEventListener("resize", onResizeDebounced); onWindowResize(); return () => { window.removeEventListener("resize", onResizeDebounced); }; }, [ref]); return [width, height]; } function useExpressionValueGetter({ attrs, expressionData }) { const cellIdMap = useMemo2(() => { const result = {}; if (attrs && attrs.rows) { for (let i = 0; i < attrs.rows.length; i++) { result[attrs.rows[i]] = i; } } return result; }, [attrs]); const getExpressionValue = useCallback2((entry) => { const cellId = entry[0]; if (cellIdMap && expressionData && expressionData[0]) { const cellIndex = cellIdMap[cellId]; const val = expressionData[0][cellIndex]; return val; } return 0; }, [cellIdMap, expressionData]); return getExpressionValue; } // src/components/shared-mui/styles.js import { makeStyles, createTheme } from "@material-ui/core/styles"; import { grey } from "@material-ui/core/colors"; var styles = makeStyles(() => ({ paper: { maxHeight: 200, overflow: "auto" }, container: { position: "relative", left: 0, top: 0 }, span: { width: "70px", textAlign: "center", paddingLeft: "2px", paddingRight: "2px" } })); var muiTheme = { dark: createTheme({ palette: { type: "dark", primary: grey, secondary: grey, primaryBackground: "#222222", primaryBackgroundHighlight: "#000000", primaryBackgroundInput: "#D3D3D3", primaryBackgroundDim: "#333333", primaryBackgroundLight: "#757575", primaryForeground: "#D3D3D3", primaryForegroundDim: "#000000", primaryForegroundActive: "#9bb7d6", secondaryBackground: "#000000", secondaryBackgroundDim: "#444444", secondaryForeground: "#D3D3D3" }, props: { MuiButtonBase: { disableRipple: true } } }), light: createTheme({ palette: { type: "light", primary: grey, secondary: grey, primaryBackground: "#F1F1F1", primaryBackgroundHighlight: "#FFFFFF", primaryBackgroundInput: "#FFFFFF", primaryBackgroundDim: "#8A8A8A", primaryBackgroundLight: "#e0e0e0", primaryForeground: "#333333", primaryForegroundDim: "#808080", primaryForegroundActive: "#0074D9", secondaryBackground: "#F1F1F1", secondaryBackgroundDim: "#C0C0C0", secondaryForeground: "#222222" }, props: { MuiButtonBase: { disableRipple: true } } }) }; // src/components/shared-mui/components.js function MuiSpan(props) { const { children } = props; const classes = styles(); return /* @__PURE__ */ React2.createElement("span", { className: classes.span }, children); } function PopperMenu(props) { const { buttonIcon, open, setOpen, children, buttonClassName, placement = "bottom-end" } = props; const classes = styles(); const anchorRef = useRef3(); const handleClick = () => { setOpen((prev) => !prev); }; const handleClose = () => { setOpen(false); }; const id = open ? "v-popover-menu" : void 0; const getTooltipContainer = useVitessceContainer(anchorRef); return /* @__PURE__ */ React2.createElement("div", { ref: anchorRef, className: classes.container }, /* @__PURE__ */ React2.createElement(IconButton, { "aria-describedby": id, onClick: handleClick, size: "small", className: buttonClassName }, buttonIcon), /* @__PURE__ */ React2.createElement(Popper, { id, open, anchorEl: anchorRef && anchorRef.current, container: getTooltipContainer, onClose: handleClose, placement, transition: true }, ({ TransitionProps }) => /* @__PURE__ */ React2.createElement(ClickAwayListener, { onClickAway: handleClose }, /* @__PURE__ */ React2.createElement(Fade, __spreadProps(__spreadValues({}, TransitionProps), { timeout: 100 }), /* @__PURE__ */ React2.createElement(Paper, { elevation: 4, className: classes.paper }, /* @__PURE__ */ React2.createElement(MenuList, null, children)))))); } // src/components/TitleInfo.js var useStyles = makeStyles2((theme) => ({ iconButton: { border: "none", marginLeft: 0, background: "none", color: theme.palette.primaryForeground, paddingLeft: "0.25em", paddingRight: "0.25em", borderRadius: "2px", "&:hover": { backgroundColor: theme.palette.primaryBackgroundLight }, "&:first-child": { marginLeft: "0.25em" }, "&:last-child": { marginRight: "0.25em" }, "& svg": { width: "0.7em", height: "0.7em", verticalAlign: "middle", overflow: "visible" } }, downloadLink: { color: theme.palette.primaryForeground } })); function SettingsIconWithArrow({ open }) { return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(SettingsIcon, null), open ? /* @__PURE__ */ React3.createElement(ArrowDropUpIcon, null) : /* @__PURE__ */ React3.createElement(ArrowDropDownIcon, null)); } function PlotOptions(props) { const { options } = props; const [open, setOpen] = useState2(false); const classes = useStyles(); return /* @__PURE__ */ React3.createElement(PopperMenu, { open, setOpen, buttonIcon: /* @__PURE__ */ React3.createElement(SettingsIconWithArrow, { open }), buttonClassName: classes.iconButton, placement: "bottom-end" }, options); } function CloudDownloadIconWithArrow({ open }) { return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(CloudDownloadIcon, null), open ? /* @__PURE__ */ React3.createElement(ArrowDropUpIcon, null) : /* @__PURE__ */ React3.createElement(ArrowDropDownIcon, null)); } function DownloadOptions(props) { const { urls } = props; const [open, setOpen] = useState2(false); const classes = useStyles(); return /* @__PURE__ */ React3.createElement(PopperMenu, { open, setOpen, buttonIcon: /* @__PURE__ */ React3.createElement(CloudDownloadIconWithArrow, { open }), buttonClassName: classes.iconButton, placement: "bottom-end" }, urls.map(({ url, name: name2 }) => /* @__PURE__ */ React3.createElement(MenuItem, { dense: true, key: url }, /* @__PURE__ */ React3.createElement(Link, { underline: "none", href: url, target: "_blank", rel: "noopener", className: classes.downloadLink }, "Download ", name2)))); } function ClosePaneButton(props) { const { removeGridComponent } = props; const classes = useStyles(); return /* @__PURE__ */ React3.createElement(IconButton2, { onClick: removeGridComponent, size: "small", className: classes.iconButton, title: "close" }, /* @__PURE__ */ React3.createElement(CloseIcon, null)); } function TitleInfo(props) { const { title: title25, info, children, isScroll, isSpatial, removeGridComponent, urls, isReady, options } = props; const childClassName = isScroll ? SCROLL_CARD : isSpatial ? BLACK_CARD : SECONDARY_CARD; return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement("div", { className: "title" }, /* @__PURE__ */ React3.createElement("div", { className: "title-left" }, title25), /* @__PURE__ */ React3.createElement("div", { className: "title-info", title: info }, info), /* @__PURE__ */ React3.createElement("div", { className: "title-buttons" }, options && /* @__PURE__ */ React3.createElement(PlotOptions, { options }), urls && urls.length > 0 && /* @__PURE__ */ React3.createElement(DownloadOptions, { urls }), /* @__PURE__ */ React3.createElement(ClosePaneButton, { removeGridComponent }))), /* @__PURE__ */ React3.createElement("div", { className: childClassName }, !isReady && /* @__PURE__ */ React3.createElement(LoadingIndicator, null), children)); } // src/components/utils.js import React4 from "react"; import { COORDINATE_SYSTEM } from "@deck.gl/core"; // src/schemas/cell-sets.schema.json var $schema = "http://json-schema.org/draft-07/schema#"; var $id = "https://github.com/vitessce/vitessce/#cell-sets"; var title = "Vitessce cell sets data"; var type = "object"; var definitions = { stringArray: { type: "array", items: { type: "string" } }, stringProbabilityTupleArray: { type: "array", items: { type: "array", additionalItems: false, items: [ { type: "string" }, { oneOf: [ { type: "number", minimum: 0, maximum: 1 }, { type: "null" } ] } ] } }, colorArray: { type: "array", items: { type: "integer", minimum: 0, maximum: 255 }, minItems: 3, maxItems: 3 }, treeNodeLeaf: { type: "object", additionalProperties: false, required: ["name"], properties: { name: { type: "string" }, color: { $ref: "#/definitions/colorArray" }, set: { $ref: "#/definitions/stringArray" } } }, treeNodeNonLeaf: { type: "object", additionalProperties: false, required: ["name"], properties: { name: { type: "string" }, color: { $ref: "#/definitions/colorArray" }, children: { type: "array", items: { $ref: "#/definitions/treeNode" } } } }, treeNode: { oneOf: [ { $ref: "#/definitions/treeNodeNonLeaf" }, { $ref: "#/definitions/treeNodeLeaf" } ] }, "version0.1.2": { type: "object", additionalProperties: false, required: ["version", "datatype", "tree"], properties: { dataset: { type: "string" }, version: { type: "string", enum: ["0.1.2"] }, datatype: { type: "string", enum: ["cell"] }, tree: { type: "array", items: { $ref: "#/definitions/treeNodeNonLeaf" } } } }, treeNodeLeafProbabilistic: { type: "object", additionalProperties: false, required: ["name"], properties: { name: { type: "string" }, color: { $ref: "#/definitions/colorArray" }, set: { $ref: "#/definitions/stringProbabilityTupleArray" } } }, treeNodeNonLeafProbabilistic: { type: "object", additionalProperties: false, required: ["name"], properties: { name: { type: "string" }, color: { $ref: "#/definitions/colorArray" }, children: { type: "array", items: { $ref: "#/definitions/treeNodeProbabilistic" } } } }, treeNodeProbabilistic: { oneOf: [ { $ref: "#/definitions/treeNodeNonLeafProbabilistic" }, { $ref: "#/definitions/treeNodeLeafProbabilistic" } ] }, "version0.1.3": { type: "object", additionalProperties: false, required: ["version", "datatype", "tree"], properties: { dataset: { type: "string" }, version: { type: "string", enum: ["0.1.3"] }, datatype: { type: "string", enum: ["cell"] }, tree: { type: "array", items: { $ref: "#/definitions/treeNodeNonLeafProbabilistic" } } } } }; var oneOf = [ { $ref: "#/definitions/version0.1.2" }, { $ref: "#/definitions/version0.1.3" } ]; var cell_sets_schema_default = { $schema, $id, title, type, definitions, oneOf }; // src/schemas/cell-sets-tabular.schema.json var $schema2 = "http://json-schema.org/draft-07/schema#"; var $id2 = "https://github.com/vitessce/vitessce/#cell-sets-tabular"; var title2 = "Vitessce cell sets data, tabular format"; var definitions2 = { colorArray: { type: "array", items: { type: "integer", minimum: 0, maximum: 255 }, minItems: 3, maxItems: 3 } }; var type2 = "array"; var items = { type: "object", additionalProperties: false, required: ["groupName", "setName", "obsId"], properties: { groupName: { type: "string" }, setName: { type: "string" }, setColor: { $ref: "#/definitions/colorArray" }, obsId: { type: "string" }, predictionScore: { oneOf: [ { type: "number", minimum: 0, maximum: 1 }, { type: "null" } ] } } }; var cell_sets_tabular_schema_default = { $schema: $schema2, $id: $id2, title: title2, definitions: definitions2, type: type2, items }; // src/components/sets/constants.js var FILE_EXTENSION_JSON = "json"; var MIME_TYPE_JSON = "application/json"; var FILE_EXTENSION_TABULAR = "csv"; var MIME_TYPE_TABULAR = "text/csv"; var SEPARATOR_TABULAR = ","; var NA_VALUE_TABULAR = "NA"; var SETS_DATATYPE_CELL = "cell"; var HIERARCHICAL_SCHEMAS = { cell: { latestVersion: "0.1.3", schema: cell_sets_schema_default } }; var TABULAR_SCHEMAS = { cell: { schema: cell_sets_tabular_schema_default } }; // src/components/utils.js function makeCellStatusMessage(cellInfoFactors) { return Object.entries(cellInfoFactors).map(([factor, value]) => `${factor}: ${value}`).join("; "); } function cellLayerDefaultProps(cells, updateStatus, setCellHighlight, setComponentHover) { return { coordinateSystem: COORDINATE_SYSTEM.CARTESIAN, data: cells, pickable: true, autoHighlight: true, stroked: true, filled: true, getElevation: 0, onHover: (info) => { if (setComponentHover) { setComponentHover(); } if (info.object) { const [cellId, cellInfo] = info.object; const { factors = {} } = cellInfo; if (updateStatus) { updateStatus(makeCellStatusMessage(factors)); } if (setCellHighlight) { setCellHighlight(cellId); } } else if (setCellHighlight) { setCellHighlight(""); } } }; } var DEFAULT_DARK_COLOR = [50, 50, 50]; var DEFAULT_LIGHT_COLOR = [200, 200, 200]; function getDefaultColor(theme) { return theme === "dark" ? DEFAULT_DARK_COLOR : DEFAULT_LIGHT_COLOR; } var PALETTE = [ [68, 119, 170], [136, 204, 238], [68, 170, 153], [17, 119, 51], [153, 153, 51], [221, 204, 119], [204, 102, 119], [136, 34, 85], [170, 68, 153] ]; var VIEWER_PALETTE = [ [0, 0, 255], [0, 255, 0], [255, 0, 255], [255, 255, 0], [0, 255, 255], [255, 255, 255], [255, 128, 0], [255, 0, 0] ]; var COLORMAP_OPTIONS = [ "viridis", "greys", "magma", "jet", "hot", "bone", "copper", "summer", "density", "inferno" ]; var DEFAULT_GL_OPTIONS = { webgl2: true }; function createDefaultUpdateCellsHover(componentName) { return (hoverInfo) => console.warn(`${componentName} updateCellsHover: ${hoverInfo.cellId}`); } function createDefaultUpdateGenesHover(componentName) { return (hoverInfo) => console.warn(`${componentName} updateGenesHover: ${hoverInfo.geneId}`); } function createDefaultUpdateTracksHover(componentName) { return (hoverInfo) => console.warn(`${componentName} updateTracksHover: ${hoverInfo}`); } function createDefaultUpdateViewInfo(componentName) { return (viewInfo) => console.warn(`${componentName} updateViewInfo: ${viewInfo}`); } function copyUint8Array(arr) { const newBuffer = new ArrayBuffer(arr.buffer.byteLength); const newArr = new Uint8Array(newBuffer); newArr.set(arr); return newArr; } function getNextNumberedNodeName(nodes, prefix) { let i = 1; if (nodes) { while (nodes.find((n) => n.name === `${prefix}${i}`)) { i++; } } return `${prefix}${i}`; } function setCellSelection(cellSelection, additionalCellSets, cellSetColor, setCellSetSelection, setAdditionalCellSets, setCellSetColor, setCellColorEncoding, prefix = "Selection ") { const CELL_SELECTIONS_LEVEL_ZERO_NAME = "My Selections"; const selectionsLevelZeroNode = additionalCellSets == null ? void 0 : additionalCellSets.tree.find((n) => n.name === CELL_SELECTIONS_LEVEL_ZERO_NAME); const nextAdditionalCellSets = { version: HIERARCHICAL_SCHEMAS[SETS_DATATYPE_CELL].latestVersion, datatype: SETS_DATATYPE_CELL, tree: [...additionalCellSets ? additionalCellSets.tree : []] }; const nextName = getNextNumberedNodeName(selectionsLevelZeroNode == null ? void 0 : selectionsLevelZeroNode.children, prefix); let colorIndex = 0; if (selectionsLevelZeroNode) { colorIndex = selectionsLevelZeroNode.children.length; selectionsLevelZeroNode.children.push({ name: nextName, set: cellSelection.map((d) => [d, null]) }); } else { nextAdditionalCellSets.tree.push({ name: CELL_SELECTIONS_LEVEL_ZERO_NAME, children: [ { name: nextName, set: cellSelection.map((d) => [d, null]) } ] }); } setAdditionalCellSets(nextAdditionalCellSets); const nextPath = ["My Selections", nextName]; setCellSetColor([ ...cellSetColor || [], { path: nextPath, color: PALETTE[colorIndex % PALETTE.length] } ]); setCellSetSelection([nextPath]); setCellColorEncoding("cellSetSelection"); } function mergeCellSets(cellSets, additionalCellSets) { return { version: HIERARCHICAL_SCHEMAS[SETS_DATATYPE_CELL].latestVersion, datatype: SETS_DATATYPE_CELL, tree: [ ...cellSets ? cellSets.tree : [], ...additionalCellSets ? additionalCellSets.tree : [] ] }; } function createWarningComponent(props) { return () => { const { title: title25, message } = props; return /* @__PURE__ */ React4.createElement("div", { className: PRIMARY_CARD }, /* @__PURE__ */ React4.createElement("h1", null, title25), /* @__PURE__ */ React4.createElement("div", null, message)); }; } function asEsModule(component) { return { __esModule: true, default: component }; } function formatBytes(bytes, decimals = 2) { if (bytes === 0) return "0 Bytes"; const k = 1024; const dm = decimals < 0 ? 0 : decimals; const sizes = ["Bytes", "KB", "MB", "GB"]; const i = Math.floor(Math.log(bytes) / Math.log(k)); return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`; } var getStatsForResolution = (loader, resolution) => { const { shape, labels } = loader[resolution]; const height = shape[labels.indexOf("y")]; const width = shape[labels.indexOf("x")]; const depth = shape[labels.indexOf("z")]; const depthDownsampled = Math.max(1, depth >> resolution); const totalBytes = 4 * height * width * depthDownsampled; return { height, width, depthDownsampled, totalBytes }; }; var canLoadResolution = (loader, resolution) => { var _a2, _b2, _c; const { totalBytes, height, width, depthDownsampled } = getStatsForResolution(loader, resolution); const maxHeapSize = ((_a2 = window.performance) == null ? void 0 : _a2.memory) && ((_c = (_b2 = window.performance) == null ? void 0 : _b2.memory) == null ? void 0 : _c.jsHeapSizeLimit) / 2; const maxSize = maxHeapSize || __pow(2, 31) - 1; return totalBytes < maxSize && height <= 2048 && depthDownsampled <= 2048 && width <= 2048 && depthDownsampled > 1; }; // src/components/data-hooks.js import { useState as useState3, useEffect as useEffect2 } from "react"; import equal2 from "fast-deep-equal"; // src/loaders/errors/AbstractLoaderError.js var AbstractLoaderError = class { constructor(message) { this.message = message; } warnInConsole() { throw new Error("The warnInConsole() method has not been implemented."); } }; // src/loaders/errors/LoaderValidationError.js var LoaderValidationError = class extends AbstractLoaderError { constructor(datasetType, datasetFileType, datasetUrl, reason) { super(`Error while validating ${datasetType}.`); this.name = "LoaderValidationError"; this.datasetType = datasetType; this.datasetFileType = datasetFileType; this.datasetUrl = datasetUrl; this.reason = reason; } warnInConsole() { const { datasetType, datasetUrl, reason } = this; console.warn(`${datasetType} from ${datasetUrl}: validation failed`, JSON.stringify(reason, null, 2)); } }; // src/loaders/errors/LoaderNotFoundError.js var LoaderNotFoundError = class extends AbstractLoaderError { constructor(datasetType, datasetFileType, datasetUrl) { super(`Error finding loader for ${datasetType}.`); this.name = "LoaderNotFoundError"; this.datasetType = datasetType; this.datasetFileType = datasetFileType; this.datasetUrl = datasetUrl; } warnInConsole() { const { datasetType, datasetFileType, datasetUrl } = this; if (datasetFileType && datasetUrl) { console.warn(`${datasetType} from ${datasetUrl}: unable to find loader for fileType ${datasetFileType}`); } else { console.warn(`${datasetType}: unable to find loader`); } } }; // src/loaders/errors/DatasetNotFoundError.js var DatasetNotFoundError = class extends AbstractLoaderError { constructor(datasetUid) { super(`Error finding dataset for ${datasetUid}. Please check that at least one dataset exists in the view config.`); this.name = "DatasetNotFoundError"; this.datasetUid = datasetUid; } warnInConsole() { const { datasetUid } = this; if (datasetUid) { console.warn(`Unable to find dataset for ${datasetUid}`); } else { console.warn("No dataset uid specified."); } } }; // node_modules/@hms-dbmi/viv/dist/viv.es.js import { COORDINATE_SYSTEM as COORDINATE_SYSTEM2, Layer, project32, picking, CompositeLayer, LayerExtension, OrthographicView, Controller, OrbitView } from "@deck.gl/core"; import { Matrix4 } from "math.gl"; import GL from "@luma.gl/constants"; import { TileLayer } from "@deck.gl/geo-layers"; import { Model, Geometry, Texture2D, isWebGL2, Texture3D } from "@luma.gl/core"; import { ProgramManager } from "@luma.gl/engine"; import { hasFeature, FEATURES } from "@luma.gl/webgl"; import { BitmapLayer as BitmapLayer$1, PolygonLayer, LineLayer, TextLayer } from "@deck.gl/layers"; import quickselect from "quickselect"; import { Plane } from "@math.gl/culling"; import React5, { PureComponent, useMemo as useMemo3 } from "react"; import DeckGL from "@deck.gl/react"; import equal from "fast-deep-equal"; import { fromUrl, fromBlob } from "geotiff"; import parser from "fast-xml-parser"; import { KeyError, openGroup, BoundsCheckError, slice, HTTPStore } from "zarr"; var fs$6 = "#define SHADER_NAME xr-layer-fragment-shader\nprecision highp float;precision highp int;precision highp SAMPLER_TYPE;\n#define GLSLIFY 1\nuniform SAMPLER_TYPE channel0;uniform SAMPLER_TYPE channel1;uniform SAMPLER_TYPE channel2;uniform SAMPLER_TYPE channel3;uniform SAMPLER_TYPE channel4;uniform SAMPLER_TYPE channel5;in vec2 vTexCoord;uniform vec2 contrastLimits[6];void main(){float intensity0=float(texture(channel0,vTexCoord).r);DECKGL_PROCESS_INTENSITY(intensity0,contrastLimits[0],0);float intensity1=float(texture(channel1,vTexCoord).r);DECKGL_PROCESS_INTENSITY(intensity1,contrastLimits[1],1);float intensity2=float(texture(channel2,vTexCoord).r);DECKGL_PROCESS_INTENSITY(intensity2,contrastLimits[2],2);float intensity3=float(texture(channel3,vTexCoord).r);DECKGL_PROCESS_INTENSITY(intensity3,contrastLimits[3],3);float intensity4=float(texture(channel4,vTexCoord).r);DECKGL_PROCESS_INTENSITY(intensity4,contrastLimits[4],4);float intensity5=float(texture(channel5,vTexCoord).r);DECKGL_PROCESS_INTENSITY(intensity5,contrastLimits[5],5);DECKGL_MUTATE_COLOR(gl_FragColor,intensity0,intensity1,intensity2,intensity3,intensity4,intensity5,vTexCoord);geometry.uv=vTexCoord;DECKGL_FILTER_COLOR(gl_FragColor,geometry);}"; var vs$1 = "#define GLSLIFY 1\n#define SHADER_NAME xr-layer-vertex-shader\nattribute vec2 texCoords;attribute vec3 positions;attribute vec3 positions64Low;attribute vec3 instancePickingColors;varying vec2 vTexCoord;void main(void){geometry.worldPosition=positions;geometry.uv=texCoords;geometry.pickingColor=instancePickingColors;gl_Position=project_position_to_clipspace(positions,positions64Low,vec3(0.),geometry.position);DECKGL_FILTER_GL_POSITION(gl_Position,geometry);vTexCoord=texCoords;vec4 color=vec4(0.);DECKGL_FILTER_COLOR(color,geometry);}"; var fs$5 = "#define GLSLIFY 1\nfloat apply_contrast_limits(float intensity,vec2 contrastLimits){return max(0.,(intensity-contrastLimits[0])/max(0.0005,(contrastLimits[1]-contrastLimits[0])));}"; var channels$1 = { name: "channel-intensity-module", defines: { SAMPLER_TYPE: "usampler2D", COLORMAP_FUNCTION: "" }, fs: fs$5 }; var MAX_COLOR_INTENSITY = 255; var DEFAULT_COLOR_OFF = [0, 0, 0]; var MAX_CHANNELS = 6; var DEFAULT_FONT_FAMILY = "-apple-system, 'Helvetica Neue', Arial, sans-serif"; var DTYPE_VALUES = { Uint8: { format: GL.R8UI, dataFormat: GL.RED_INTEGER, type: GL.UNSIGNED_BYTE, max: __pow(2, 8) - 1, sampler: "usampler2D" }, Uint16: { format: GL.R16UI, dataFormat: GL.RED_INTEGER, type: GL.UNSIGNED_SHORT, max: __pow(2, 16) - 1, sampler: "usampler2D" }, Uint32: { format: GL.R32UI, dataFormat: GL.RED_INTEGER, type: GL.UNSIGNED_INT, max: __pow(2, 32) - 1, sampler: "usampler2D" }, Float32: