@vitessce/all 4.0.0 → 4.0.2
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/{GeometryAndMeshXR-DGeJ5ZBr.js → GeometryAndMeshXR-DngaDWBF.js} +2 -2
- package/dist/{ReactNeuroglancer-Do72MK3I.js → ReactNeuroglancer-DSiLDSuM.js} +169 -57
- package/dist/{XREnterButton-vmEhdF4L.js → XREnterButton-Beha7PBD.js} +1 -1
- package/dist/{XRSceneComponents-DnZLSAJz.js → XRSceneComponents-CNuqVsYi.js} +3 -1
- package/dist/{XRWrapper-C94X82Mb.js → XRWrapper-BsV3wgJG.js} +3 -2
- package/dist/{deflate-VdN3pn_b.js → deflate-BnG3V84V.js} +1 -1
- package/dist/{higlass-DL7cd1YR.js → higlass-4OKx7mdy.js} +1 -1
- package/dist/{index-GwbVVPa9.js → index-B8FH88N6.js} +1022 -214
- package/dist/{index-Dau2mo3I.js → index-B9h9IQaz.js} +1 -1
- package/dist/{index-tp3-aWWe.js → index-CwGBUQIk.js} +18 -6
- package/dist/index.js +8 -8
- package/dist/{jpeg-CYgQz5aG.js → jpeg-9VJS3-Bw.js} +1 -1
- package/dist/{lerc-C-Llf71G.js → lerc-D1J26SPX.js} +1 -1
- package/dist/{lzw-DJhX6Tr-.js → lzw-xVcb3-tK.js} +1 -1
- package/dist/{packbits-BOwAxrqR.js → packbits-Dm4fdK8S.js} +1 -1
- package/dist/{raw-BX1y7Iy_.js → raw-UWcztCkw.js} +1 -1
- package/dist/{webimage-DCU5-f3Q.js → webimage-C-QWVV-f.js} +1 -1
- package/dist/xrStore-Dhi1LSJi.js +8 -0
- package/dist-tsc/base-plugins.d.ts +1 -1
- package/dist-tsc/base-plugins.d.ts.map +1 -1
- package/dist-tsc/base-plugins.js +1 -0
- package/dist-tsc/base-plugins.js.map +1 -1
- package/package.json +34 -34
- package/src/base-plugins.ts +1 -0
- package/dist/xrStore-BymedRtx.js +0 -8
|
@@ -5440,12 +5440,12 @@ function baseIsEqual$3(value2, other, bitmask, customizer, stack2) {
|
|
|
5440
5440
|
var now$4 = function() {
|
|
5441
5441
|
return root$d.Date.now();
|
|
5442
5442
|
};
|
|
5443
|
-
var FUNC_ERROR_TEXT$
|
|
5443
|
+
var FUNC_ERROR_TEXT$3 = "Expected a function";
|
|
5444
5444
|
var nativeMax$3 = Math.max, nativeMin$1 = Math.min;
|
|
5445
5445
|
function debounce$5(func, wait2, options) {
|
|
5446
5446
|
var lastArgs, lastThis, maxWait, result, timerId, lastCallTime, lastInvokeTime = 0, leading = false, maxing = false, trailing = true;
|
|
5447
5447
|
if (typeof func != "function") {
|
|
5448
|
-
throw new TypeError(FUNC_ERROR_TEXT$
|
|
5448
|
+
throw new TypeError(FUNC_ERROR_TEXT$3);
|
|
5449
5449
|
}
|
|
5450
5450
|
wait2 = toNumber$3(wait2) || 0;
|
|
5451
5451
|
if (isObject$f(options)) {
|
|
@@ -5603,6 +5603,22 @@ var range$e = createRange();
|
|
|
5603
5603
|
function sum$6(array2) {
|
|
5604
5604
|
return array2 && array2.length ? baseSum(array2, identity$h) : 0;
|
|
5605
5605
|
}
|
|
5606
|
+
var FUNC_ERROR_TEXT$2 = "Expected a function";
|
|
5607
|
+
function throttle$1(func, wait2, options) {
|
|
5608
|
+
var leading = true, trailing = true;
|
|
5609
|
+
if (typeof func != "function") {
|
|
5610
|
+
throw new TypeError(FUNC_ERROR_TEXT$2);
|
|
5611
|
+
}
|
|
5612
|
+
if (isObject$f(options)) {
|
|
5613
|
+
leading = "leading" in options ? !!options.leading : leading;
|
|
5614
|
+
trailing = "trailing" in options ? !!options.trailing : trailing;
|
|
5615
|
+
}
|
|
5616
|
+
return debounce$5(func, wait2, {
|
|
5617
|
+
"leading": leading,
|
|
5618
|
+
"maxWait": wait2,
|
|
5619
|
+
"trailing": trailing
|
|
5620
|
+
});
|
|
5621
|
+
}
|
|
5606
5622
|
var INFINITY = 1 / 0;
|
|
5607
5623
|
var createSet = !(Set$3 && 1 / setToArray$2(new Set$3([, -0]))[1] == INFINITY) ? noop$h : function(values3) {
|
|
5608
5624
|
return new Set$3(values3);
|
|
@@ -9436,6 +9452,7 @@ const CoordinationType$1 = {
|
|
|
9436
9452
|
SPATIAL_CHANNEL_LABELS_VISIBLE: "spatialChannelLabelsVisible",
|
|
9437
9453
|
SPATIAL_CHANNEL_LABELS_ORIENTATION: "spatialChannelLabelsOrientation",
|
|
9438
9454
|
SPATIAL_CHANNEL_LABEL_SIZE: "spatialChannelLabelSize",
|
|
9455
|
+
SPATIAL_CHANNELS_SORT_ORDER: "spatialChannelsSortOrder",
|
|
9439
9456
|
// Multi-sample / comparative
|
|
9440
9457
|
SAMPLE_TYPE: "sampleType",
|
|
9441
9458
|
SAMPLE_SELECTION: "sampleSelection",
|
|
@@ -9488,7 +9505,9 @@ const ViewHelpMapping = {
|
|
|
9488
9505
|
OBS_SET_COMPOSITION_BAR_PLOT: "The set composition bar plot displays the results of a compositional analysis conducted using the scCODA method (Büttner et al. 2021 Nature Communications).",
|
|
9489
9506
|
FEATURE_SET_ENRICHMENT_BAR_PLOT: "The feature set enrichment bar plot displays the results of a hypergeometric test applied to the differential expression test results to identify enriched pathway gene sets.",
|
|
9490
9507
|
SAMPLE_SET_PAIR_MANAGER: "Select pairs of sample groups.",
|
|
9491
|
-
FEATURE_STATS_TABLE: "This table displays per-feature statistics, for example, from a differential expression test."
|
|
9508
|
+
FEATURE_STATS_TABLE: "This table displays per-feature statistics, for example, from a differential expression test.",
|
|
9509
|
+
LAYER_CONTROLLER_BETA: "The spatial layer controller provides an interface for manipulating the visualization layers displayed in the spatial view.",
|
|
9510
|
+
SPATIAL_BETA: "The spatial view displays (potentially layered) spatially-resolved data including RGB or multiplexed images, segmentations of observations (bitmask- or polygon-based), and/or points (e.g., representing FISH transcripts)."
|
|
9492
9511
|
};
|
|
9493
9512
|
({
|
|
9494
9513
|
// For new file types
|
|
@@ -10039,6 +10058,7 @@ const COMPONENT_COORDINATION_TYPES = {
|
|
|
10039
10058
|
CoordinationType$1.SPATIAL_CHANNEL_LABELS_VISIBLE,
|
|
10040
10059
|
CoordinationType$1.SPATIAL_CHANNEL_LABELS_ORIENTATION,
|
|
10041
10060
|
CoordinationType$1.SPATIAL_CHANNEL_LABEL_SIZE,
|
|
10061
|
+
CoordinationType$1.SPATIAL_CHANNELS_SORT_ORDER,
|
|
10042
10062
|
CoordinationType$1.PHOTOMETRIC_INTERPRETATION
|
|
10043
10063
|
],
|
|
10044
10064
|
[ViewType$1.HEATMAP]: [
|
|
@@ -10220,7 +10240,8 @@ const COMPONENT_COORDINATION_TYPES = {
|
|
|
10220
10240
|
CoordinationType$1.LEGEND_VISIBLE,
|
|
10221
10241
|
CoordinationType$1.SPATIAL_CHANNEL_LABELS_VISIBLE,
|
|
10222
10242
|
CoordinationType$1.SPATIAL_CHANNEL_LABELS_ORIENTATION,
|
|
10223
|
-
CoordinationType$1.SPATIAL_CHANNEL_LABEL_SIZE
|
|
10243
|
+
CoordinationType$1.SPATIAL_CHANNEL_LABEL_SIZE,
|
|
10244
|
+
CoordinationType$1.SPATIAL_CHANNELS_SORT_ORDER
|
|
10224
10245
|
],
|
|
10225
10246
|
[ViewType$1.GENOMIC_PROFILES]: [
|
|
10226
10247
|
CoordinationType$1.DATASET,
|
|
@@ -10931,7 +10952,18 @@ const ngPrecomputedMeshSchema = z.object({
|
|
|
10931
10952
|
const ngPointAnnotationSchema = z.object({
|
|
10932
10953
|
projectionAnnotationSpacing: z.number(),
|
|
10933
10954
|
featureIndexProp: z.string().optional().describe("The name of the Neuroglancer AnnotationProperty containing feature IDs. For example, specify 'gene' to use prop_gene() in the Neuroglancer shader code."),
|
|
10934
|
-
pointIndexProp: z.string().optional().describe("The name of the Neuroglancer AnnotationProperty containing point IDs. For example, specify 'point_id' to use prop_point_id() in the Neuroglancer shader code.")
|
|
10955
|
+
pointIndexProp: z.string().optional().describe("The name of the Neuroglancer AnnotationProperty containing point IDs. For example, specify 'point_id' to use prop_point_id() in the Neuroglancer shader code."),
|
|
10956
|
+
transform: z.object({
|
|
10957
|
+
matrix: z.array(z.array(z.number())),
|
|
10958
|
+
outputDimensions: z.record(z.tuple([z.number(), z.string()]))
|
|
10959
|
+
}).optional().describe("A coordinate transformation matrix to apply to the annotation layer source to map annotation coordinates to the global coordinate space."),
|
|
10960
|
+
// Note: See comments in neuroglancer-sorger.js
|
|
10961
|
+
// We may remove these in the future, pending clarification
|
|
10962
|
+
// to questions in the tissue-map-tools repo
|
|
10963
|
+
// - https://github.com/hms-dbmi/tissue-map-tools/issues/20
|
|
10964
|
+
// - https://github.com/hms-dbmi/tissue-map-tools/issues/38
|
|
10965
|
+
quantitativeColorProp: z.string().optional(),
|
|
10966
|
+
quantitativeColorMax: z.number().optional()
|
|
10935
10967
|
}).partial().nullable();
|
|
10936
10968
|
const obsEmbeddingAnndataSchema = annDataObsEmbedding;
|
|
10937
10969
|
const obsSpotsAnndataSchema = annDataObsLocations;
|
|
@@ -18344,7 +18376,7 @@ const { tss } = createTss({
|
|
|
18344
18376
|
},
|
|
18345
18377
|
"usePlugin": useMuiThemeStyleOverridesPlugin
|
|
18346
18378
|
});
|
|
18347
|
-
const useStyles$
|
|
18379
|
+
const useStyles$y = tss.create({});
|
|
18348
18380
|
function createChainedFunction$1(...funcs) {
|
|
18349
18381
|
return funcs.reduce((acc, func) => {
|
|
18350
18382
|
if (func == null) {
|
|
@@ -72632,7 +72664,7 @@ const Popper = React.forwardRef((props, ref2) => {
|
|
|
72632
72664
|
}, [handlePopperRef]);
|
|
72633
72665
|
React.useImperativeHandle(popperRefProp, () => popperRef.current, []);
|
|
72634
72666
|
const [exited, setExited] = React.useState(true);
|
|
72635
|
-
const { theme } = useStyles$
|
|
72667
|
+
const { theme } = useStyles$y();
|
|
72636
72668
|
const rtlPlacement = flipPlacement(initialPlacement, theme);
|
|
72637
72669
|
const [placement, setPlacement] = React.useState(rtlPlacement);
|
|
72638
72670
|
React.useEffect(() => {
|
|
@@ -73366,7 +73398,7 @@ var VariableSizeList$1 = /* @__PURE__ */ createListComponent({
|
|
|
73366
73398
|
});
|
|
73367
73399
|
const VariableSizeList = VariableSizeList$1;
|
|
73368
73400
|
const LIST_ROW_HEIGHT$1 = 48;
|
|
73369
|
-
const useStyles$
|
|
73401
|
+
const useStyles$x = makeStyles()(() => ({
|
|
73370
73402
|
searchInput: {
|
|
73371
73403
|
lineHeight: "initial",
|
|
73372
73404
|
height: "auto !important"
|
|
@@ -73406,7 +73438,7 @@ const ListboxComponent$1 = React__default.forwardRef((props, ref2) => {
|
|
|
73406
73438
|
});
|
|
73407
73439
|
function SimpleAutocomplete(props) {
|
|
73408
73440
|
const { getMatches, onChange, textInputLabel = "Enter a gene", getItemLabel = (option) => option.label } = props;
|
|
73409
|
-
const { classes: classes2 } = useStyles$
|
|
73441
|
+
const { classes: classes2 } = useStyles$x();
|
|
73410
73442
|
const [potentialItems, setPotentialItems] = useState([]);
|
|
73411
73443
|
const handleInputChange = async (_event, value2) => {
|
|
73412
73444
|
if (!value2) {
|
|
@@ -82956,7 +82988,7 @@ function defaultUrlTransform(value2) {
|
|
|
82956
82988
|
}
|
|
82957
82989
|
return "";
|
|
82958
82990
|
}
|
|
82959
|
-
const useStyles$
|
|
82991
|
+
const useStyles$w = makeStyles()((theme) => ({
|
|
82960
82992
|
description: {
|
|
82961
82993
|
"& p, details, table": {
|
|
82962
82994
|
fontSize: "80%",
|
|
@@ -82993,7 +83025,7 @@ const useStyles$v = makeStyles()((theme) => ({
|
|
|
82993
83025
|
}));
|
|
82994
83026
|
function Description(props) {
|
|
82995
83027
|
const { description: description2, metadata: metadata2, descriptionType } = props;
|
|
82996
|
-
const { classes: classes2 } = useStyles$
|
|
83028
|
+
const { classes: classes2 } = useStyles$w();
|
|
82997
83029
|
return jsxs("div", { className: classes2.description, children: [descriptionType && descriptionType === DescriptionType.MARKDOWN ? jsx$1(Markdown, { children: description2 }) : jsx$1("p", { children: description2 }), metadata2 && Array.from(metadata2.entries()).map(([layerIndex, { name: layerName, metadata: metadataRecord }]) => metadataRecord && Object.entries(metadataRecord).length > 0 ? jsxs("details", { children: [jsx$1("summary", { children: layerName }), jsx$1("div", { className: classes2.metadataContainer, children: jsx$1("table", { children: jsx$1("tbody", { children: Object.entries(metadataRecord).map(([key2, value2]) => jsxs("tr", { children: [jsx$1("th", { title: key2, children: key2 }), jsx$1("td", { title: value2, children: value2 })] }, key2)) }) }) })] }, layerIndex) : null)] });
|
|
82998
83030
|
}
|
|
82999
83031
|
function DescriptionSubscriber(props) {
|
|
@@ -91245,6 +91277,37 @@ function dataToCellSetsTree(data2, options) {
|
|
|
91245
91277
|
return cellSetsTree;
|
|
91246
91278
|
}
|
|
91247
91279
|
const schemeRdBu = [[103, 0, 31], [178, 24, 43], [214, 96, 77], [244, 165, 130], [253, 219, 199], [247, 247, 247], [209, 229, 240], [146, 197, 222], [67, 147, 195], [33, 102, 172], [5, 48, 97]];
|
|
91280
|
+
const schemePlasma = [[13, 8, 135], [16, 7, 136], [19, 7, 137], [22, 7, 138], [25, 6, 140], [27, 6, 141], [29, 6, 142], [32, 6, 143], [34, 6, 144], [36, 6, 145], [38, 5, 145], [40, 5, 146], [42, 5, 147], [44, 5, 148], [46, 5, 149], [47, 5, 150], [49, 5, 151], [51, 5, 151], [53, 4, 152], [55, 4, 153], [56, 4, 154], [58, 4, 154], [60, 4, 155], [62, 4, 156], [63, 4, 156], [65, 4, 157], [67, 3, 158], [68, 3, 158], [70, 3, 159], [72, 3, 159], [73, 3, 160], [75, 3, 161], [76, 2, 161], [78, 2, 162], [80, 2, 162], [81, 2, 163], [83, 2, 163], [85, 2, 164], [86, 1, 164], [88, 1, 164], [89, 1, 165], [91, 1, 165], [92, 1, 166], [94, 1, 166], [96, 1, 166], [97, 0, 167], [99, 0, 167], [100, 0, 167], [102, 0, 167], [103, 0, 168], [105, 0, 168], [106, 0, 168], [108, 0, 168], [110, 0, 168], [111, 0, 168], [113, 0, 168], [114, 1, 168], [116, 1, 168], [117, 1, 168], [119, 1, 168], [120, 1, 168], [122, 2, 168], [123, 2, 168], [125, 3, 168], [126, 3, 168], [128, 4, 168], [129, 4, 167], [131, 5, 167], [132, 5, 167], [134, 6, 166], [135, 7, 166], [136, 8, 166], [138, 9, 165], [139, 10, 165], [141, 11, 165], [142, 12, 164], [143, 13, 164], [145, 14, 163], [146, 15, 163], [148, 16, 162], [149, 17, 161], [150, 19, 161], [152, 20, 160], [153, 21, 159], [154, 22, 159], [156, 23, 158], [157, 24, 157], [158, 25, 157], [160, 26, 156], [161, 27, 155], [162, 29, 154], [163, 30, 154], [165, 31, 153], [166, 32, 152], [167, 33, 151], [168, 34, 150], [170, 35, 149], [171, 36, 148], [172, 38, 148], [173, 39, 147], [174, 40, 146], [176, 41, 145], [177, 42, 144], [178, 43, 143], [179, 44, 142], [180, 46, 141], [181, 47, 140], [182, 48, 139], [183, 49, 138], [184, 50, 137], [186, 51, 136], [187, 52, 136], [188, 53, 135], [189, 55, 134], [190, 56, 133], [191, 57, 132], [192, 58, 131], [193, 59, 130], [194, 60, 129], [195, 61, 128], [196, 62, 127], [197, 64, 126], [198, 65, 125], [199, 66, 124], [200, 67, 123], [201, 68, 122], [202, 69, 122], [203, 70, 121], [204, 71, 120], [204, 73, 119], [205, 74, 118], [206, 75, 117], [207, 76, 116], [208, 77, 115], [209, 78, 114], [210, 79, 113], [211, 81, 113], [212, 82, 112], [213, 83, 111], [213, 84, 110], [214, 85, 109], [215, 86, 108], [216, 87, 107], [217, 88, 106], [218, 90, 106], [218, 91, 105], [219, 92, 104], [220, 93, 103], [221, 94, 102], [222, 95, 101], [222, 97, 100], [223, 98, 99], [224, 99, 99], [225, 100, 98], [226, 101, 97], [226, 102, 96], [227, 104, 95], [228, 105, 94], [229, 106, 93], [229, 107, 93], [230, 108, 92], [231, 110, 91], [231, 111, 90], [232, 112, 89], [233, 113, 88], [233, 114, 87], [234, 116, 87], [235, 117, 86], [235, 118, 85], [236, 119, 84], [237, 121, 83], [237, 122, 82], [238, 123, 81], [239, 124, 81], [239, 126, 80], [240, 127, 79], [240, 128, 78], [241, 129, 77], [241, 131, 76], [242, 132, 75], [243, 133, 75], [243, 135, 74], [244, 136, 73], [244, 137, 72], [245, 139, 71], [245, 140, 70], [246, 141, 69], [246, 143, 68], [247, 144, 68], [247, 145, 67], [247, 147, 66], [248, 148, 65], [248, 149, 64], [249, 151, 63], [249, 152, 62], [249, 154, 62], [250, 155, 61], [250, 156, 60], [250, 158, 59], [251, 159, 58], [251, 161, 57], [251, 162, 56], [252, 163, 56], [252, 165, 55], [252, 166, 54], [252, 168, 53], [252, 169, 52], [253, 171, 51], [253, 172, 51], [253, 174, 50], [253, 175, 49], [253, 177, 48], [253, 178, 47], [253, 180, 47], [253, 181, 46], [254, 183, 45], [254, 184, 44], [254, 186, 44], [254, 187, 43], [254, 189, 42], [254, 190, 42], [254, 192, 41], [253, 194, 41], [253, 195, 40], [253, 197, 39], [253, 198, 39], [253, 200, 39], [253, 202, 38], [253, 203, 38], [252, 205, 37], [252, 206, 37], [252, 208, 37], [252, 210, 37], [251, 211, 36], [251, 213, 36], [251, 215, 36], [250, 216, 36], [250, 218, 36], [249, 220, 36], [249, 221, 37], [248, 223, 37], [248, 225, 37], [247, 226, 37], [247, 228, 37], [246, 230, 38], [246, 232, 38], [245, 233, 38], [245, 235, 39], [244, 237, 39], [243, 238, 39], [243, 240, 39], [242, 242, 39], [241, 244, 38], [241, 245, 37], [240, 247, 36], [240, 249, 33]];
|
|
91281
|
+
const schemeViridis = [[68, 1, 84], [68, 2, 86], [69, 4, 87], [69, 5, 89], [70, 7, 90], [70, 8, 92], [70, 10, 93], [70, 11, 94], [71, 13, 96], [71, 14, 97], [71, 16, 99], [71, 17, 100], [71, 19, 101], [72, 20, 103], [72, 22, 104], [72, 23, 105], [72, 24, 106], [72, 26, 108], [72, 27, 109], [72, 28, 110], [72, 30, 111], [72, 31, 112], [72, 32, 113], [72, 34, 115], [72, 35, 116], [72, 36, 117], [72, 38, 118], [72, 39, 119], [72, 40, 120], [72, 42, 121], [72, 43, 122], [72, 44, 123], [72, 46, 124], [72, 47, 125], [72, 48, 126], [72, 50, 127], [72, 51, 128], [72, 52, 129], [72, 53, 130], [72, 55, 131], [72, 56, 132], [72, 57, 133], [72, 59, 134], [72, 60, 135], [72, 61, 136], [72, 63, 137], [72, 64, 137], [72, 65, 138], [72, 67, 139], [72, 68, 140], [72, 69, 141], [72, 71, 142], [72, 72, 143], [72, 73, 144], [72, 75, 145], [72, 76, 146], [72, 77, 147], [72, 79, 148], [72, 80, 149], [72, 82, 150], [72, 83, 150], [72, 84, 151], [72, 86, 152], [72, 87, 153], [72, 88, 154], [72, 90, 155], [71, 91, 156], [71, 92, 157], [71, 94, 158], [71, 95, 158], [71, 97, 159], [71, 98, 160], [71, 99, 161], [71, 101, 162], [71, 102, 163], [71, 103, 164], [71, 105, 164], [71, 106, 165], [71, 108, 166], [71, 109, 167], [71, 110, 168], [71, 112, 169], [71, 113, 169], [71, 114, 170], [71, 116, 171], [71, 117, 172], [70, 119, 173], [70, 120, 174], [70, 121, 174], [70, 123, 175], [70, 124, 176], [70, 125, 177], [70, 127, 178], [70, 128, 178], [70, 130, 179], [70, 131, 180], [70, 132, 181], [70, 134, 182], [70, 135, 182], [70, 136, 183], [70, 138, 184], [70, 139, 185], [70, 141, 186], [70, 142, 186], [70, 143, 187], [70, 145, 188], [70, 146, 189], [70, 148, 189], [70, 149, 190], [70, 150, 191], [70, 152, 192], [70, 153, 192], [70, 155, 193], [70, 156, 194], [70, 157, 195], [70, 159, 195], [70, 160, 196], [70, 162, 197], [70, 163, 198], [70, 164, 198], [70, 166, 199], [70, 167, 200], [71, 169, 200], [71, 170, 201], [71, 171, 202], [71, 173, 203], [71, 174, 203], [71, 176, 204], [71, 177, 205], [71, 178, 205], [72, 180, 206], [72, 181, 207], [72, 183, 207], [72, 184, 208], [73, 185, 209], [73, 187, 209], [73, 188, 210], [74, 190, 211], [74, 191, 211], [74, 192, 212], [75, 194, 213], [75, 195, 213], [76, 197, 214], [76, 198, 214], [77, 199, 215], [77, 201, 216], [78, 202, 216], [78, 204, 217], [79, 205, 217], [79, 207, 218], [80, 208, 218], [81, 209, 219], [81, 211, 220], [82, 212, 220], [83, 214, 221], [83, 215, 221], [84, 216, 222], [85, 218, 222], [85, 219, 223], [86, 221, 223], [87, 222, 224], [88, 224, 224], [88, 225, 225], [89, 226, 225], [90, 228, 226], [91, 229, 226], [92, 231, 227], [92, 232, 227], [93, 234, 228], [94, 235, 228], [95, 236, 229], [96, 238, 229], [97, 239, 230], [97, 241, 230], [98, 242, 231], [99, 244, 231], [100, 245, 232], [101, 246, 232], [102, 248, 233], [103, 249, 233], [104, 251, 234], [105, 252, 234]];
|
|
91282
|
+
const schemeJet = Array.from({ length: 256 }, (_, i2) => {
|
|
91283
|
+
const t4 = i2 / 255;
|
|
91284
|
+
let r3;
|
|
91285
|
+
let g2;
|
|
91286
|
+
let b2;
|
|
91287
|
+
if (t4 < 0.125) {
|
|
91288
|
+
r3 = 0;
|
|
91289
|
+
g2 = 0;
|
|
91290
|
+
b2 = 0.5 + t4 * 4;
|
|
91291
|
+
} else if (t4 < 0.375) {
|
|
91292
|
+
r3 = 0;
|
|
91293
|
+
g2 = (t4 - 0.125) * 4;
|
|
91294
|
+
b2 = 1;
|
|
91295
|
+
} else if (t4 < 0.625) {
|
|
91296
|
+
r3 = (t4 - 0.375) * 4;
|
|
91297
|
+
g2 = 1;
|
|
91298
|
+
b2 = 1 - (t4 - 0.375) * 4;
|
|
91299
|
+
} else if (t4 < 0.875) {
|
|
91300
|
+
r3 = 1;
|
|
91301
|
+
g2 = 1 - (t4 - 0.625) * 4;
|
|
91302
|
+
b2 = 0;
|
|
91303
|
+
} else {
|
|
91304
|
+
r3 = 1 - (t4 - 0.875) * 4;
|
|
91305
|
+
g2 = 0;
|
|
91306
|
+
b2 = 0;
|
|
91307
|
+
}
|
|
91308
|
+
return [Math.round(r3 * 255), Math.round(g2 * 255), Math.round(b2 * 255)];
|
|
91309
|
+
});
|
|
91310
|
+
const schemeGreys = Array.from({ length: 256 }, (_, i2) => [i2, i2, i2]);
|
|
91248
91311
|
function rgbSpline$1(spline) {
|
|
91249
91312
|
return (colors2) => {
|
|
91250
91313
|
const n3 = colors2.length;
|
|
@@ -91282,7 +91345,15 @@ function basis$2(values3) {
|
|
|
91282
91345
|
};
|
|
91283
91346
|
}
|
|
91284
91347
|
const interpolateRgbBasis = rgbSpline$1(basis$2);
|
|
91348
|
+
function interpolateSequentialMulti(range2) {
|
|
91349
|
+
const n3 = range2.length;
|
|
91350
|
+
return (t4) => range2[Math.max(0, Math.min(n3 - 1, Math.floor(t4 * n3)))];
|
|
91351
|
+
}
|
|
91285
91352
|
interpolateRgbBasis(schemeRdBu);
|
|
91353
|
+
const interpolatePlasma = interpolateSequentialMulti(schemePlasma);
|
|
91354
|
+
const interpolateViridis = interpolateSequentialMulti(schemeViridis);
|
|
91355
|
+
const interpolateJet = interpolateSequentialMulti(schemeJet);
|
|
91356
|
+
const interpolateGreys = interpolateSequentialMulti(schemeGreys);
|
|
91286
91357
|
function getCellColors(params2) {
|
|
91287
91358
|
const { cellSets, cellSetSelection, cellSetColor, obsIndex, theme } = params2;
|
|
91288
91359
|
if (cellSetSelection && cellSets) {
|
|
@@ -98064,7 +98135,7 @@ const Tooltip$2 = /* @__PURE__ */ React.forwardRef((props, ref2) => {
|
|
|
98064
98135
|
}, extraProps), getChildren());
|
|
98065
98136
|
});
|
|
98066
98137
|
const nodeHeight = 32;
|
|
98067
|
-
const useStyles$
|
|
98138
|
+
const useStyles$v = makeStyles()((theme) => ({
|
|
98068
98139
|
setsManager: {
|
|
98069
98140
|
position: "relative",
|
|
98070
98141
|
width: "100%",
|
|
@@ -98231,7 +98302,7 @@ const useStyles$u = makeStyles()((theme) => ({
|
|
|
98231
98302
|
}));
|
|
98232
98303
|
function SetsManagerTreeGlobalStyles(props) {
|
|
98233
98304
|
const { classes: classes2 } = props;
|
|
98234
|
-
const { theme } = useStyles$
|
|
98305
|
+
const { theme } = useStyles$y();
|
|
98235
98306
|
return jsx$1(ScopedGlobalStyles, { parentClassName: classes2.setsManagerTree, styles: {
|
|
98236
98307
|
".rc-tree": {
|
|
98237
98308
|
paddingLeft: "0",
|
|
@@ -98572,7 +98643,7 @@ function HelpTooltipGlobalStyles(props) {
|
|
|
98572
98643
|
}
|
|
98573
98644
|
function PopoverGlobalStyles(props) {
|
|
98574
98645
|
const { classes: classes2 } = props;
|
|
98575
|
-
const { theme } = useStyles$
|
|
98646
|
+
const { theme } = useStyles$y();
|
|
98576
98647
|
return jsx$1(ScopedGlobalStyles, { parentClassName: classes2.popover, styles: {
|
|
98577
98648
|
".rc-tooltip-inner": {
|
|
98578
98649
|
boxSizing: "border-box",
|
|
@@ -103256,7 +103327,7 @@ function NamedSetNodeStatic(props) {
|
|
|
103256
103327
|
const onClick = level === 0 && !expanded ? () => onCheckLevel(nodeKey, nextLevelToCheck) : () => onNodeView(path2);
|
|
103257
103328
|
const tooltipProps = disableTooltip ? { visible: false } : {};
|
|
103258
103329
|
const popoverMenuConfig = makeNodeViewMenuConfig(props);
|
|
103259
|
-
const { classes: classes2 } = useStyles$
|
|
103330
|
+
const { classes: classes2 } = useStyles$v();
|
|
103260
103331
|
return jsxs("span", { children: [jsx$1(HelpTooltip, { title: tooltipText, ...tooltipProps, children: jsx$1("button", { type: "button", onClick, onKeyPress: (e3) => callbackOnKeyPress(e3, "v", () => onNodeView(path2)), className: classes2.titleButton, children: title2 }) }), popoverMenuConfig.length > 0 ? jsx$1(PopoverMenu, { menuConfig: makeNodeViewMenuConfig(props), color: level > 0 && editable ? color2 || getDefaultColor(theme) : null, setColor: (c2) => onNodeSetColor(path2, c2), children: jsx$1("span", { children: jsx$1(SvgMenu, { className: classes2.nodeMenuIcon, "aria-label": "Open Node View Menu" }) }) }) : null, level > 0 && isChecking ? checkbox2 : null, level > 0 && jsx$1("span", { className: classes2.nodeSizeLabel, children: niceSize })] });
|
|
103261
103332
|
}
|
|
103262
103333
|
function NamedSetNodeEditing(props) {
|
|
@@ -103268,7 +103339,7 @@ function NamedSetNodeEditing(props) {
|
|
|
103268
103339
|
onNodeSetName(path2, currentTitle, true);
|
|
103269
103340
|
}
|
|
103270
103341
|
}
|
|
103271
|
-
const { classes: classes2 } = useStyles$
|
|
103342
|
+
const { classes: classes2 } = useStyles$v();
|
|
103272
103343
|
return jsxs("span", { className: classes2.titleButtonWithInput, children: [jsx$1("input", {
|
|
103273
103344
|
// eslint-disable-next-line jsx-a11y/no-autofocus
|
|
103274
103345
|
autoFocus: true,
|
|
@@ -103294,7 +103365,7 @@ function LevelsButtons(props) {
|
|
|
103294
103365
|
onCheckLevel(nodeKey, newLevel);
|
|
103295
103366
|
}
|
|
103296
103367
|
}
|
|
103297
|
-
const { classes: classes2 } = useStyles$
|
|
103368
|
+
const { classes: classes2 } = useStyles$v();
|
|
103298
103369
|
return jsx$1("div", { className: classes2.levelButtonsContainer, children: range$e(1, height2 + 1).map((i2) => {
|
|
103299
103370
|
const isChecked = isEqual$3(path2, checkedLevelPath) && i2 === checkedLevelIndex;
|
|
103300
103371
|
return jsx$1("div", { children: jsx$1(HelpTooltip, { title: getLevelTooltipText(i2), children: jsx$1("input", { className: clsx(classes2.levelRadioButton, { [classes2.levelRadioButtonChecked]: isChecked && !hasColorEncoding }), type: "checkbox", value: i2, checked: isChecked && hasColorEncoding, onChange: onCheck }) }) }, i2);
|
|
@@ -103378,7 +103449,7 @@ let TreeNode$1 = class TreeNode extends TreeNode$2 {
|
|
|
103378
103449
|
};
|
|
103379
103450
|
function PlusButton(props) {
|
|
103380
103451
|
const { datatype, onError, onImportTree, onCreateLevelZeroNode, importable, editable } = props;
|
|
103381
|
-
const { classes: classes2 } = useStyles$
|
|
103452
|
+
const { classes: classes2 } = useStyles$v();
|
|
103382
103453
|
const onImport = useCallback((importHandler, mimeType) => () => {
|
|
103383
103454
|
const uploadInputNode = document.createElement("input");
|
|
103384
103455
|
uploadInputNode.setAttribute("type", "file");
|
|
@@ -103495,7 +103566,7 @@ function SetsManager(props) {
|
|
|
103495
103566
|
}, onNodeCheckNewName, onNodeSetIsEditing: setIsEditingNodeName, onNodeRemove, onExportLevelZeroNodeJSON, onExportLevelZeroNodeTabular, onExportSetJSON, disableTooltip: isDragging, onDragStart: () => setIsDragging(true), onDragEnd: () => setIsDragging(false), children: renderTreeNodes(node2.children, readOnly, newPath) }, pathToKey(newPath));
|
|
103496
103567
|
});
|
|
103497
103568
|
}
|
|
103498
|
-
const { classes: classes2 } = useStyles$
|
|
103569
|
+
const { classes: classes2 } = useStyles$v();
|
|
103499
103570
|
return jsxs("div", { className: classes2.setsManager, children: [jsx$1(SetsManagerTreeGlobalStyles, { classes: classes2 }), jsxs("div", { className: classes2.setsManagerTree, children: [jsx$1(Tree$1, { draggable: false, checkable, checkedKeys: setSelectionKeys, expandedKeys: setExpansionKeys, autoExpandParent, onCheck: (checkedKeys, info2) => onCheckNode(info2.node.props.nodeKey, info2.checked), onExpand: (expandedKeys, info2) => onExpandNode(expandedKeys, info2.node.props.nodeKey, info2.expanded), children: renderTreeNodes(processedSets.tree, true, []) }), jsx$1(Tree$1, { draggable: true, checkable, checkedKeys: additionalSetSelectionKeys, expandedKeys: additionalSetExpansionKeys, autoExpandParent, onCheck: (checkedKeys, info2) => onCheckNode(info2.node.props.nodeKey, info2.checked), onExpand: (expandedKeys, info2) => onExpandNode(expandedKeys, info2.node.props.nodeKey, info2.expanded), onDrop: (info2) => {
|
|
103500
103571
|
const { eventKey: dropKey } = info2.node.props;
|
|
103501
103572
|
const { eventKey: dragKey } = info2.dragNode.props;
|
|
@@ -209460,22 +209531,22 @@ async function getDecoder(fileDirectory) {
|
|
|
209460
209531
|
const Decoder = await importFn();
|
|
209461
209532
|
return new Decoder(fileDirectory);
|
|
209462
209533
|
}
|
|
209463
|
-
addDecoder([void 0, 1], () => import("./raw-
|
|
209464
|
-
addDecoder(5, () => import("./lzw-
|
|
209534
|
+
addDecoder([void 0, 1], () => import("./raw-UWcztCkw.js").then((m2) => m2.default));
|
|
209535
|
+
addDecoder(5, () => import("./lzw-xVcb3-tK.js").then((m2) => m2.default));
|
|
209465
209536
|
addDecoder(6, () => {
|
|
209466
209537
|
throw new Error("old style JPEG compression is not supported.");
|
|
209467
209538
|
});
|
|
209468
|
-
addDecoder(7, () => import("./jpeg-
|
|
209469
|
-
addDecoder([8, 32946], () => import("./deflate-
|
|
209470
|
-
addDecoder(32773, () => import("./packbits-
|
|
209539
|
+
addDecoder(7, () => import("./jpeg-9VJS3-Bw.js").then((m2) => m2.default));
|
|
209540
|
+
addDecoder([8, 32946], () => import("./deflate-BnG3V84V.js").then((m2) => m2.default));
|
|
209541
|
+
addDecoder(32773, () => import("./packbits-Dm4fdK8S.js").then((m2) => m2.default));
|
|
209471
209542
|
addDecoder(
|
|
209472
209543
|
34887,
|
|
209473
|
-
() => import("./lerc-
|
|
209544
|
+
() => import("./lerc-D1J26SPX.js").then(async (m2) => {
|
|
209474
209545
|
await m2.zstd.init();
|
|
209475
209546
|
return m2;
|
|
209476
209547
|
}).then((m2) => m2.default)
|
|
209477
209548
|
);
|
|
209478
|
-
addDecoder(50001, () => import("./webimage-
|
|
209549
|
+
addDecoder(50001, () => import("./webimage-C-QWVV-f.js").then((m2) => m2.default));
|
|
209479
209550
|
function copyNewSize(array2, width2, height2, samplesPerPixel = 1) {
|
|
209480
209551
|
return new (Object.getPrototypeOf(array2)).constructor(width2 * height2 * samplesPerPixel);
|
|
209481
209552
|
}
|
|
@@ -226249,7 +226320,7 @@ class ContourLayerWithText extends ContourLayer {
|
|
|
226249
226320
|
}
|
|
226250
226321
|
ContourLayerWithText.layerName = "ContourLayerWithText";
|
|
226251
226322
|
ContourLayerWithText.defaultProps = defaultProps;
|
|
226252
|
-
const useStyles$
|
|
226323
|
+
const useStyles$u = makeStyles()(() => ({
|
|
226253
226324
|
toolButton: {
|
|
226254
226325
|
display: "inline-flex",
|
|
226255
226326
|
"&:active": {
|
|
@@ -226311,12 +226382,12 @@ const useStyles$t = makeStyles()(() => ({
|
|
|
226311
226382
|
}));
|
|
226312
226383
|
function IconTool(props) {
|
|
226313
226384
|
const { alt, onClick, isActive: isActive2, children: children3 } = props;
|
|
226314
|
-
const { classes: classes2 } = useStyles$
|
|
226385
|
+
const { classes: classes2 } = useStyles$u();
|
|
226315
226386
|
return jsx$1("button", { className: clsx(classes2.toolIcon, { [classes2.toolActive]: isActive2 }), onClick, type: "button", title: alt, children: children3 });
|
|
226316
226387
|
}
|
|
226317
226388
|
function IconButton(props) {
|
|
226318
226389
|
const { alt, onClick, children: children3 } = props;
|
|
226319
|
-
const { classes: classes2 } = useStyles$
|
|
226390
|
+
const { classes: classes2 } = useStyles$u();
|
|
226320
226391
|
return jsx$1("button", { className: clsx(classes2.toolIcon, classes2.toolButton), onClick, type: "button", title: alt, children: children3 });
|
|
226321
226392
|
}
|
|
226322
226393
|
function ToolMenu(props) {
|
|
@@ -226324,14 +226395,14 @@ function ToolMenu(props) {
|
|
|
226324
226395
|
const lassoIconAltText = "Select lasso";
|
|
226325
226396
|
const { setActiveTool, activeTool, visibleTools = { pan: true, selectLasso: true, recenter: true }, recenterOnClick = () => {
|
|
226326
226397
|
} } = props;
|
|
226327
|
-
const { classes: classes2 } = useStyles$
|
|
226398
|
+
const { classes: classes2 } = useStyles$u();
|
|
226328
226399
|
const onRecenterButtonCLick = () => {
|
|
226329
226400
|
recenterOnClick();
|
|
226330
226401
|
};
|
|
226331
226402
|
return jsxs("div", { className: classes2.tool, children: [visibleTools.pan && jsx$1(IconTool, { alt: pointerIconAltText, onClick: () => setActiveTool(null), isActive: activeTool === null, children: jsx$1(SvgNearMe, {}) }), visibleTools.selectLasso ? jsx$1(IconTool, { alt: lassoIconAltText, onClick: () => setActiveTool(distEs6Exports$2.SELECTION_TYPE.POLYGON), isActive: activeTool === distEs6Exports$2.SELECTION_TYPE.POLYGON, children: jsx$1(SvgSelectionLasso, {}) }) : null, visibleTools.recenter ? jsx$1(IconButton, { alt: "click to recenter", onClick: () => onRecenterButtonCLick(), "aria-label": "Recenter scatterplot view", children: jsx$1(CenterFocusStrong, {}) }) : null] });
|
|
226332
226403
|
}
|
|
226333
226404
|
const getCursorWithTool = () => "crosshair";
|
|
226334
|
-
const getCursor = (interactionState) => interactionState.isDragging ? "grabbing" : "
|
|
226405
|
+
const getCursor = (interactionState) => interactionState.isDragging ? "grabbing" : "grab";
|
|
226335
226406
|
function getOnHoverCallback(obsIndex, setObsHighlight, setComponentHover) {
|
|
226336
226407
|
return (info2) => {
|
|
226337
226408
|
if (setComponentHover) {
|
|
@@ -227481,7 +227552,7 @@ function ScatterplotOptions(props) {
|
|
|
227481
227552
|
id: `feature-aggregation-strategy-${scatterplotOptionsId}`
|
|
227482
227553
|
}, children: FEATURE_AGGREGATION_STRATEGIES$2.map((opt) => jsx$1("option", { value: opt, children: capitalize$3(opt) }, opt)) }) })] }) : null] });
|
|
227483
227554
|
}
|
|
227484
|
-
const useStyles$
|
|
227555
|
+
const useStyles$t = makeStyles()((theme) => ({
|
|
227485
227556
|
tooltipAnchor: {
|
|
227486
227557
|
position: "relative",
|
|
227487
227558
|
width: "0px",
|
|
@@ -227512,7 +227583,7 @@ const useStyles$s = makeStyles()((theme) => ({
|
|
|
227512
227583
|
function Tooltip3(props) {
|
|
227513
227584
|
const { x: x2, y: y2, parentWidth, parentHeight, children: children3 } = props;
|
|
227514
227585
|
const ref2 = useRef();
|
|
227515
|
-
const { classes: classes2 } = useStyles$
|
|
227586
|
+
const { classes: classes2 } = useStyles$t();
|
|
227516
227587
|
const [placementX, setPlacementX] = useState("start");
|
|
227517
227588
|
const [placementY, setPlacementY] = useState("bottom");
|
|
227518
227589
|
const getTooltipContainer = useVitessceContainer(ref2);
|
|
@@ -227528,7 +227599,7 @@ function Tooltip3(props) {
|
|
|
227528
227599
|
}, [x2, y2, parentWidth, parentHeight]);
|
|
227529
227600
|
return jsx$1("div", { ref: ref2, className: classes2.tooltipAnchor, children: ref2 && ref2.current ? jsx$1(Popper, { open: true, anchorEl: ref2.current, container: getTooltipContainer, transition: true, placement: `${placementY}-${placementX}`, children: jsx$1(Paper, { elevation: 8, className: classes2.tooltipContent, children: children3 }) }) : null });
|
|
227530
227601
|
}
|
|
227531
|
-
const useStyles$
|
|
227602
|
+
const useStyles$s = makeStyles()((theme) => ({
|
|
227532
227603
|
cellEmphasisCrosshair: {
|
|
227533
227604
|
zIndex: 50,
|
|
227534
227605
|
position: "absolute",
|
|
@@ -227539,7 +227610,7 @@ const useStyles$r = makeStyles()((theme) => ({
|
|
|
227539
227610
|
}));
|
|
227540
227611
|
function Tooltip2D(props) {
|
|
227541
227612
|
const { parentUuid, sourceUuid, x: x2, y: y2, parentWidth, parentHeight, children: children3 } = props;
|
|
227542
|
-
const { classes: classes2 } = useStyles$
|
|
227613
|
+
const { classes: classes2 } = useStyles$s();
|
|
227543
227614
|
if (x2 < 0 || x2 > parentWidth || y2 < 0 || y2 > parentHeight) {
|
|
227544
227615
|
return null;
|
|
227545
227616
|
}
|
|
@@ -231451,7 +231522,7 @@ function getXlinkHref(cmap) {
|
|
|
231451
231522
|
const xlinkHref = ramp(color2.copy().domain(quantize$3(interpolate$1$1(0, 1), n3))).toDataURL();
|
|
231452
231523
|
return xlinkHref;
|
|
231453
231524
|
}
|
|
231454
|
-
const useStyles$
|
|
231525
|
+
const useStyles$r = makeStyles()(() => ({
|
|
231455
231526
|
legend: {
|
|
231456
231527
|
position: "relative",
|
|
231457
231528
|
// Needed for absolute positioning of slider overlay
|
|
@@ -231648,7 +231719,7 @@ function Legend(props) {
|
|
|
231648
231719
|
contourThresholds
|
|
231649
231720
|
} = props;
|
|
231650
231721
|
const svgRef = useRef(null);
|
|
231651
|
-
const { classes: classes2 } = useStyles$
|
|
231722
|
+
const { classes: classes2 } = useStyles$r();
|
|
231652
231723
|
const [localRange, setLocalRange] = useState(featureValueColormapRange);
|
|
231653
231724
|
useEffect(() => {
|
|
231654
231725
|
setLocalRange(featureValueColormapRange);
|
|
@@ -231982,7 +232053,7 @@ function Legend(props) {
|
|
|
231982
232053
|
}
|
|
231983
232054
|
} })] })] });
|
|
231984
232055
|
}
|
|
231985
|
-
const useStyles$
|
|
232056
|
+
const useStyles$q = makeStyles()(() => ({
|
|
231986
232057
|
multiLegend: {
|
|
231987
232058
|
position: "absolute",
|
|
231988
232059
|
top: "0px",
|
|
@@ -232009,7 +232080,7 @@ function MultiLegend(props) {
|
|
|
232009
232080
|
pointLayerCoordination,
|
|
232010
232081
|
pointMultiIndicesData
|
|
232011
232082
|
} = props;
|
|
232012
|
-
const { classes: classes2 } = useStyles$
|
|
232083
|
+
const { classes: classes2 } = useStyles$q();
|
|
232013
232084
|
const reversedSegmentationLayerScopes = useMemo$1(() => [...segmentationLayerScopes || []].reverse(), [segmentationLayerScopes]);
|
|
232014
232085
|
const reversedSpotLayerScopes = useMemo$1(() => [...spotLayerScopes || []].reverse(), [spotLayerScopes]);
|
|
232015
232086
|
const reversedPointLayerScopes = useMemo$1(() => [...pointLayerScopes || []].reverse(), [pointLayerScopes]);
|
|
@@ -232102,7 +232173,7 @@ function MultiLegend(props) {
|
|
|
232102
232173
|
}) : null;
|
|
232103
232174
|
}) : null] });
|
|
232104
232175
|
}
|
|
232105
|
-
const useStyles$
|
|
232176
|
+
const useStyles$p = makeStyles()(() => ({
|
|
232106
232177
|
channelNamesLegendContainer: {
|
|
232107
232178
|
position: "absolute",
|
|
232108
232179
|
bottom: "0px",
|
|
@@ -232125,7 +232196,7 @@ const useStyles$o = makeStyles()(() => ({
|
|
|
232125
232196
|
}));
|
|
232126
232197
|
function ChannelNamesLegend(props) {
|
|
232127
232198
|
const { images, imageLayerScopes, imageLayerCoordination, imageChannelScopesByLayer, imageChannelCoordination } = props;
|
|
232128
|
-
const { classes: classes2 } = useStyles$
|
|
232199
|
+
const { classes: classes2 } = useStyles$p();
|
|
232129
232200
|
const reversedImageLayerScopes = useMemo$1(() => [...imageLayerScopes || []].reverse(), [imageLayerScopes]);
|
|
232130
232201
|
return jsx$1("div", { className: classes2.channelNamesLegendContainer, children: imageLayerScopes ? reversedImageLayerScopes.map((layerScope) => {
|
|
232131
232202
|
const layerCoordination = imageLayerCoordination[0][layerScope];
|
|
@@ -253669,7 +253740,7 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
|
|
|
253669
253740
|
this.viewInfoDidUpdate();
|
|
253670
253741
|
const shallowDiff2 = (propName) => prevProps[propName] !== this.props[propName];
|
|
253671
253742
|
const shallowDiffByLayer2 = (propName, scopeName) => prevProps?.[propName]?.[scopeName] !== this.props?.[propName]?.[scopeName];
|
|
253672
|
-
const
|
|
253743
|
+
const shallowDiffByChannel2 = (propName, firstName, secondName) => prevProps?.[propName]?.[firstName]?.[secondName] !== this.props?.[propName]?.[firstName]?.[secondName];
|
|
253673
253744
|
const shallowDiffByLayerCoordination = (propName, layerScope) => prevProps?.[propName]?.[0]?.[layerScope] !== this.props?.[propName]?.[0]?.[layerScope];
|
|
253674
253745
|
const shallowDiffByChannelCoordination = (propName, layerScope, channelScope) => prevProps?.[propName]?.[0]?.[layerScope]?.[channelScope] !== this.props?.[propName]?.[0]?.[layerScope]?.[channelScope];
|
|
253675
253746
|
let forceUpdate = false;
|
|
@@ -253690,7 +253761,7 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
|
|
|
253690
253761
|
} else {
|
|
253691
253762
|
this.props.segmentationLayerScopes?.forEach((layerScope) => {
|
|
253692
253763
|
this.props.segmentationChannelScopesByLayer?.[layerScope]?.forEach((channelScope) => {
|
|
253693
|
-
if (
|
|
253764
|
+
if (shallowDiffByChannel2("obsSegmentationsLocations", layerScope, channelScope)) {
|
|
253694
253765
|
this.onUpdateSegmentationsLocationsData(layerScope, channelScope);
|
|
253695
253766
|
forceUpdate = true;
|
|
253696
253767
|
}
|
|
@@ -253703,7 +253774,7 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
|
|
|
253703
253774
|
} else {
|
|
253704
253775
|
this.props.segmentationLayerScopes?.forEach((layerScope) => {
|
|
253705
253776
|
this.props.segmentationChannelScopesByLayer?.[layerScope]?.forEach((channelScope) => {
|
|
253706
|
-
if (
|
|
253777
|
+
if (shallowDiffByChannel2("obsSegmentationsSets", layerScope, channelScope) || shallowDiffByChannelCoordination("segmentationChannelCoordination", layerScope, channelScope)) {
|
|
253707
253778
|
this.onUpdateSegmentationsSetsData(layerScope, channelScope);
|
|
253708
253779
|
forceUpdate = true;
|
|
253709
253780
|
}
|
|
@@ -253716,7 +253787,7 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
|
|
|
253716
253787
|
} else {
|
|
253717
253788
|
this.props.segmentationLayerScopes?.forEach((layerScope) => {
|
|
253718
253789
|
this.props.segmentationChannelScopesByLayer?.[layerScope]?.forEach((channelScope) => {
|
|
253719
|
-
if (
|
|
253790
|
+
if (shallowDiffByChannel2("segmentationMatrixIndices", layerScope, channelScope)) {
|
|
253720
253791
|
this.onUpdateSegmentationsIndexData(layerScope, channelScope);
|
|
253721
253792
|
forceUpdate = true;
|
|
253722
253793
|
}
|
|
@@ -253729,7 +253800,7 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
|
|
|
253729
253800
|
} else {
|
|
253730
253801
|
this.props.segmentationLayerScopes.forEach((layerScope) => {
|
|
253731
253802
|
this.props.segmentationChannelScopesByLayer?.[layerScope]?.forEach((channelScope) => {
|
|
253732
|
-
if (
|
|
253803
|
+
if (shallowDiffByChannel2("segmentationMatrixIndices", layerScope, channelScope) || shallowDiffByChannel2("segmentationMultiExpressionData", layerScope, channelScope)) {
|
|
253733
253804
|
this.onUpdateSegmentationsExpressionData(layerScope, channelScope);
|
|
253734
253805
|
forceUpdate = true;
|
|
253735
253806
|
}
|
|
@@ -253983,12 +254054,12 @@ class ErrorBoundary extends React__default.Component {
|
|
|
253983
254054
|
}
|
|
253984
254055
|
}
|
|
253985
254056
|
const LazySpatialThree = React__default.lazy(async () => {
|
|
253986
|
-
const { SpatialWrapper: SpatialWrapper2 } = await import("./index-
|
|
254057
|
+
const { SpatialWrapper: SpatialWrapper2 } = await import("./index-CwGBUQIk.js").then((n3) => n3.a);
|
|
253987
254058
|
return { default: SpatialWrapper2 };
|
|
253988
254059
|
});
|
|
253989
254060
|
const SpatialThreeAdapter = React__default.forwardRef((props, ref2) => jsx$1("div", { ref: ref2, style: { width: "100%", height: "100%" }, children: jsx$1(ErrorBoundary, { fallback: jsx$1("div", { children: "3D spatial view is not available in this environment." }), children: jsx$1(Suspense, { fallback: jsx$1("div", { children: "Loading..." }), children: jsx$1(LazySpatialThree, { ...props }) }) }) }));
|
|
253990
254061
|
const LazySpatialAccelerated = React__default.lazy(async () => {
|
|
253991
|
-
const { SpatialWrapper: SpatialWrapper2 } = await import("./index-
|
|
254062
|
+
const { SpatialWrapper: SpatialWrapper2 } = await import("./index-B9h9IQaz.js");
|
|
253992
254063
|
return { default: SpatialWrapper2 };
|
|
253993
254064
|
});
|
|
253994
254065
|
const SpatialAcceleratedAdapter = React__default.forwardRef((props, ref2) => jsx$1("div", { ref: ref2, style: { width: "100%", height: "100%" }, children: jsx$1(ErrorBoundary, { fallback: jsx$1("div", { children: "3D spatial view is not available in this environment." }), children: jsx$1(Suspense, { fallback: jsx$1("div", { children: "Loading..." }), children: jsx$1(LazySpatialAccelerated, { ...props }) }) }) }));
|
|
@@ -254165,7 +254236,8 @@ function SpatialSubscriber(props) {
|
|
|
254165
254236
|
bitmaskValueIsIndex = false,
|
|
254166
254237
|
// TODO: move to coordination type
|
|
254167
254238
|
three: threeFor3d = false,
|
|
254168
|
-
accelerated: acceleratedFor3d = false
|
|
254239
|
+
accelerated: acceleratedFor3d = false,
|
|
254240
|
+
helpText = ViewHelpMapping.SPATIAL_BETA
|
|
254169
254241
|
} = props;
|
|
254170
254242
|
const loaders = useLoaders();
|
|
254171
254243
|
const setComponentHover = useSetComponentHover();
|
|
@@ -254609,7 +254681,7 @@ function SpatialSubscriber(props) {
|
|
|
254609
254681
|
}
|
|
254610
254682
|
}
|
|
254611
254683
|
};
|
|
254612
|
-
return jsxs(TitleInfo, { title: title2, info: subtitle, isSpatial: true, urls: urls2, theme, closeButtonVisible, downloadButtonVisible, removeGridComponent, isReady, errors, children: [shouldUseThree ? acceleratedFor3d ? jsx$1(SpatialAcceleratedAdapter, { ref: threeRef, uuid: uuid2, width: width2, height: height2, theme, hideTools: !isSelectable, rotation: [rotationX, rotationY, rotationZ], setRotationX, setRotationY, setRotationZ, targetT, targetZ, viewState: isValidViewState ? {
|
|
254684
|
+
return jsxs(TitleInfo, { title: title2, info: subtitle, isSpatial: true, urls: urls2, theme, closeButtonVisible, downloadButtonVisible, removeGridComponent, isReady, errors, helpText, children: [shouldUseThree ? acceleratedFor3d ? jsx$1(SpatialAcceleratedAdapter, { ref: threeRef, uuid: uuid2, width: width2, height: height2, theme, hideTools: !isSelectable, rotation: [rotationX, rotationY, rotationZ], setRotationX, setRotationY, setRotationZ, targetT, targetZ, viewState: isValidViewState ? {
|
|
254613
254685
|
zoom: zoom2,
|
|
254614
254686
|
target: [targetX2, targetY2, targetZ],
|
|
254615
254687
|
rotationX,
|
|
@@ -262060,7 +262132,7 @@ _defineProperty$3(WindowScroller, "defaultProps", {
|
|
|
262060
262132
|
serverHeight: 0,
|
|
262061
262133
|
serverWidth: 0
|
|
262062
262134
|
});
|
|
262063
|
-
const useStyles$
|
|
262135
|
+
const useStyles$o = makeStyles()((theme) => ({
|
|
262064
262136
|
selectableTable: {
|
|
262065
262137
|
flex: "1 1 auto",
|
|
262066
262138
|
outline: "none"
|
|
@@ -262209,7 +262281,7 @@ function SelectableTable(props) {
|
|
|
262209
262281
|
onChange(null);
|
|
262210
262282
|
}
|
|
262211
262283
|
}, [selectedRows, allowMultiple]);
|
|
262212
|
-
const { classes: classes2 } = useStyles$
|
|
262284
|
+
const { classes: classes2 } = useStyles$o();
|
|
262213
262285
|
const inputUuid = v4$1();
|
|
262214
262286
|
const rowRenderer = ({ index: index2, style: style2 }) => (
|
|
262215
262287
|
// eslint-disable-next-line jsx-a11y/interactive-supports-focus
|
|
@@ -262234,7 +262306,7 @@ const FEATURELIST_SORT_OPTIONS = [
|
|
|
262234
262306
|
"original"
|
|
262235
262307
|
];
|
|
262236
262308
|
const ALT_COLNAME = "Alternate ID";
|
|
262237
|
-
const useStyles$
|
|
262309
|
+
const useStyles$n = makeStyles()(() => ({
|
|
262238
262310
|
searchBar: {
|
|
262239
262311
|
marginTop: "10px",
|
|
262240
262312
|
marginLeft: "10px",
|
|
@@ -262247,7 +262319,7 @@ const useStyles$m = makeStyles()(() => ({
|
|
|
262247
262319
|
}));
|
|
262248
262320
|
function FeatureList(props) {
|
|
262249
262321
|
const { width: width2, height: height2, hasColorEncoding, geneList = [], featureLabelsMap, geneSelection = [], geneFilter = null, setGeneSelection, enableMultiSelect, showFeatureTable, featureListSort, featureListSortKey, hasFeatureLabels, primaryColumnName } = props;
|
|
262250
|
-
const { classes: classes2 } = useStyles$
|
|
262322
|
+
const { classes: classes2 } = useStyles$n();
|
|
262251
262323
|
const [searchTerm, setSearchTerm] = useState("");
|
|
262252
262324
|
const selectableTableSortKey = featureListSortKey === "featureIndex" ? "key" : "name";
|
|
262253
262325
|
const searchResults = useMemo$1(() => geneList.filter((gene) => gene.toLowerCase().includes(searchTerm.toLowerCase()) || featureLabelsMap?.get(gene)?.toLowerCase().includes(searchTerm.toLowerCase()) || featureLabelsMap?.get(cleanFeatureId(gene))?.toLowerCase().includes(searchTerm.toLowerCase())), [geneList, searchTerm, featureLabelsMap]);
|
|
@@ -262312,7 +262384,7 @@ function FeatureListOptions(props) {
|
|
|
262312
262384
|
const { classes: classes2 } = usePlotOptionsStyles();
|
|
262313
262385
|
return jsxs(OptionsContainer, { children: [children3, jsxs(TableRow, { children: [jsx$1(TableCell, { className: classes2.labelCell, variant: "head", scope: "row", children: jsx$1("label", { htmlFor: `feature-list-sort-option-${featureListId}`, children: "Sort Ordering" }) }), jsx$1(TableCell, { variant: "body", children: jsx$1(OptionSelect, { className: classes2.select, value: featureListSort, onChange: handleFeatureListSortChange, inputProps: {
|
|
262314
262386
|
id: `feature-list-sort-option-${featureListId}`
|
|
262315
|
-
}, children: FEATURELIST_SORT_OPTIONS.map((option) => jsx$1("option", { value: option, children: option }, option)) }) })] }), hasFeatureLabels ? jsxs(Fragment, { children: [jsxs(TableRow, { children: [jsx$1(TableCell, { className: classes2.labelCell, variant: "head", scope: "row", children: jsx$1("label", { htmlFor: `feature-list-sort-key-${featureListId}`, children: "Sort Key" }) }), jsx$1(TableCell, { variant: "body", children: jsx$1(OptionSelect, { className: classes2.select, disabled: featureListSort === "original", value: featureListSortKey, onChange: handleFeatureListSortKeyChange, inputProps: {
|
|
262387
|
+
}, children: FEATURELIST_SORT_OPTIONS.map((option) => jsx$1("option", { value: option, children: capitalize$3(option) }, option)) }) })] }), hasFeatureLabels ? jsxs(Fragment, { children: [jsxs(TableRow, { children: [jsx$1(TableCell, { className: classes2.labelCell, variant: "head", scope: "row", children: jsx$1("label", { htmlFor: `feature-list-sort-key-${featureListId}`, children: "Sort Key" }) }), jsx$1(TableCell, { variant: "body", children: jsx$1(OptionSelect, { className: classes2.select, disabled: featureListSort === "original", value: featureListSortKey, onChange: handleFeatureListSortKeyChange, inputProps: {
|
|
262316
262388
|
"aria-label": "Select the feature list sort key",
|
|
262317
262389
|
id: `feature-list-sort-key-${featureListId}`
|
|
262318
262390
|
}, children: hasFeatureLabels ? jsxs(Fragment, { children: [jsx$1("option", { value: "featureLabels", children: primaryColumnName }), jsx$1("option", { value: "featureIndex", children: ALT_COLNAME })] }) : jsx$1("option", { value: "featureIndex", children: primaryColumnName }) }) })] }), jsxs(TableRow, { children: [jsx$1(TableCell, { className: classes2.labelCell, variant: "head", scope: "row", children: jsx$1("label", { htmlFor: `feature-list-show-alternative-ids-${featureListId}`, children: "Show Alternate IDs" }) }), jsx$1(TableCell, { className: classes2.inputCell, variant: "body", children: jsx$1(Checkbox$1, { className: classes2.tableCheckbox, checked: showFeatureTable, onChange: handleShowTableChange, name: "feature-list-show-table", color: "default", slotProps: { input: {
|
|
@@ -262320,7 +262392,7 @@ function FeatureListOptions(props) {
|
|
|
262320
262392
|
id: `feature-list-show-alternative-ids-${featureListId}`
|
|
262321
262393
|
} } }) })] })] }) : null] });
|
|
262322
262394
|
}
|
|
262323
|
-
const useStyles$
|
|
262395
|
+
const useStyles$m = makeStyles()((theme) => ({
|
|
262324
262396
|
featureListContainer: {
|
|
262325
262397
|
width: "100%",
|
|
262326
262398
|
height: "100%",
|
|
@@ -262335,7 +262407,7 @@ function FeatureListSubscriber(props) {
|
|
|
262335
262407
|
const loaders = useLoaders();
|
|
262336
262408
|
const coordinationScopes = useCoordinationScopes(coordinationScopesRaw);
|
|
262337
262409
|
const [width2, height2, containerRef] = useGridItemSize();
|
|
262338
|
-
const { classes: classes2 } = useStyles$
|
|
262410
|
+
const { classes: classes2 } = useStyles$m();
|
|
262339
262411
|
const [{ dataset, obsType, featureType, featureSelection: geneSelection, featureFilter: geneFilter, obsColorEncoding: cellColorEncoding }, { setFeatureSelection: setGeneSelection, setFeatureFilter: setGeneFilter, setFeatureHighlight: setGeneHighlight, setObsColorEncoding: setCellColorEncoding }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType$1.FEATURE_LIST], coordinationScopes);
|
|
262340
262412
|
const variablesLabel = variablesLabelOverride || featureType;
|
|
262341
262413
|
const title2 = titleOverride || `${capitalize$3(variablesLabel)} List`;
|
|
@@ -262470,7 +262542,7 @@ const useSelectionSliderStyles = makeStyles()(() => ({
|
|
|
262470
262542
|
backgroundColor: "rgba(128, 128, 128, 0.7)"
|
|
262471
262543
|
}
|
|
262472
262544
|
}));
|
|
262473
|
-
const useStyles$
|
|
262545
|
+
const useStyles$l = makeStyles()((theme) => ({
|
|
262474
262546
|
paletteContainer: {
|
|
262475
262547
|
width: "70px",
|
|
262476
262548
|
height: "40px",
|
|
@@ -262491,10 +262563,10 @@ const useStyles$k = makeStyles()((theme) => ({
|
|
|
262491
262563
|
}
|
|
262492
262564
|
}));
|
|
262493
262565
|
const ColorPalette = ({ handleChange }) => {
|
|
262494
|
-
const { classes: classes2 } = useStyles$
|
|
262566
|
+
const { classes: classes2 } = useStyles$l();
|
|
262495
262567
|
return jsx$1("div", { className: classes2.paletteContainer, "aria-label": "Color swatch", children: VIEWER_PALETTE.map((color2) => jsx$1(IconButton$1, { className: classes2.button, onClick: () => handleChange(color2), "aria-label": `Change color to ${color2}`, children: jsx$1(LensIcon, { fontSize: "small", style: { color: `rgb(${color2})` }, className: classes2.icon }) }, color2)) });
|
|
262496
262568
|
};
|
|
262497
|
-
const useStyles$
|
|
262569
|
+
const useStyles$k = makeStyles()(() => ({
|
|
262498
262570
|
menuButton: {
|
|
262499
262571
|
backgroundColor: "transparent"
|
|
262500
262572
|
},
|
|
@@ -262513,7 +262585,7 @@ function MuiSpan(props) {
|
|
|
262513
262585
|
}
|
|
262514
262586
|
function ChannelOptions$1({ handlePropertyChange, handleChannelRemove, handleIQRUpdate }) {
|
|
262515
262587
|
const [open2, setOpen] = useState(false);
|
|
262516
|
-
const { classes: classes2 } = useStyles$
|
|
262588
|
+
const { classes: classes2 } = useStyles$k();
|
|
262517
262589
|
const handleColorSelect = (color2) => {
|
|
262518
262590
|
handlePropertyChange("color", color2);
|
|
262519
262591
|
};
|
|
@@ -263130,7 +263202,7 @@ function LayerController$1(props) {
|
|
|
263130
263202
|
minWidth: "50%"
|
|
263131
263203
|
} })] }), jsx$1(TabPanel, { value: tab2, index: 0, children: FullController }), jsx$1(TabPanel, { value: tab2, index: 1, style: { marginTop: 4 }, children: jsx$1(VolumeOptions, { loader: loader2, handleSlicerSetting, handleRenderingModeChange: setRenderingMode, renderingMode, xSlice, ySlice, zSlice, use3d, setViewState, spatialHeight, spatialWidth, modelMatrix: modelMatrix2 }) })] }) : FullController, shouldShowRemoveLayerButton ? jsx$1(Button, { onClick: handleLayerRemove, fullWidth: true, variant: "outlined", style: buttonStyles, size: "small", children: "Remove Image Layer" }) : null] })] });
|
|
263132
263204
|
}
|
|
263133
|
-
const useStyles$
|
|
263205
|
+
const useStyles$j = makeStyles()(() => ({
|
|
263134
263206
|
addButton: {
|
|
263135
263207
|
marginTop: "10px",
|
|
263136
263208
|
marginBottom: "10px",
|
|
@@ -263142,7 +263214,7 @@ function ImageAddIcon() {
|
|
|
263142
263214
|
}
|
|
263143
263215
|
function ImageAddButton({ imageOptions, handleImageAdd }) {
|
|
263144
263216
|
const [open2, setOpen] = useState(false);
|
|
263145
|
-
const { classes: classes2 } = useStyles$
|
|
263217
|
+
const { classes: classes2 } = useStyles$j();
|
|
263146
263218
|
const handleAdd = (imgData) => {
|
|
263147
263219
|
setOpen((prev2) => !prev2);
|
|
263148
263220
|
handleImageAdd(imgData);
|
|
@@ -263474,7 +263546,7 @@ const useEllipsisMenuStyles = makeStyles()(() => ({
|
|
|
263474
263546
|
padding: "4px"
|
|
263475
263547
|
}
|
|
263476
263548
|
}));
|
|
263477
|
-
const useStyles$
|
|
263549
|
+
const useStyles$i = makeStyles()(() => ({
|
|
263478
263550
|
colorPickerPaper: {
|
|
263479
263551
|
overflow: "hidden",
|
|
263480
263552
|
"& > ul": {
|
|
@@ -263532,7 +263604,7 @@ function ChannelColorPickerMenu(props) {
|
|
|
263532
263604
|
setColor2([rgb2.r, rgb2.g, rgb2.b]);
|
|
263533
263605
|
}
|
|
263534
263606
|
}
|
|
263535
|
-
const { classes: classes2 } = useStyles$
|
|
263607
|
+
const { classes: classes2 } = useStyles$i();
|
|
263536
263608
|
const currentColor = color2 ? colorArrayToString(color2) : colorArrayToString(getDefaultColor(theme));
|
|
263537
263609
|
const isWritable = typeof setColor2 === "function";
|
|
263538
263610
|
const derivedOpen = isWritable ? isStaticColor && visible ? open2 : false : false;
|
|
@@ -263540,7 +263612,7 @@ function ChannelColorPickerMenu(props) {
|
|
|
263540
263612
|
[classes2.colorIconOutline]: theme !== "dark" && isEqual$3(color2, [255, 255, 255])
|
|
263541
263613
|
}), style: { backgroundColor: currentColor } }) : isColormap && visible && featureValueColormap ? jsx$1("div", { className: classes2.colorIcon, children: jsx$1("svg", { width: "18", height: "18", children: jsx$1("image", { x: 0, y: 0, width: 18, height: 18, preserveAspectRatio: "none", href: getXlinkHref(featureValueColormap), clipPath: "inset(0% round 4px)" }) }) }) : jsx$1("div", { className: classes2.colorIcon }), buttonClassName: classes2.colorIconButton, withPaper: true, paperClassName: classes2.colorPickerPaper, "aria-label": "Open color picker menu", children: jsx$1(Twitter$1, { className: classes2.colorPicker, disableAlpha: true, width: 108, triangle: "hide", colors: defaultPalette, color: currentColor, onChangeComplete: handleColorChange }) });
|
|
263542
263614
|
}
|
|
263543
|
-
const useStyles$
|
|
263615
|
+
const useStyles$h = makeStyles()(() => ({
|
|
263544
263616
|
layerTypeSpotIcon: {
|
|
263545
263617
|
height: "100%",
|
|
263546
263618
|
marginLeft: "1px",
|
|
@@ -263553,7 +263625,7 @@ const useStyles$g = makeStyles()(() => ({
|
|
|
263553
263625
|
function SpotLayerEllipsisMenu(props) {
|
|
263554
263626
|
const { strokeWidth, setStrokeWidth, filled, setFilled, featureSelection, obsColorEncoding, setObsColorEncoding, featureValueColormap, setFeatureValueColormap, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible } = props;
|
|
263555
263627
|
const [open2, setOpen] = useState(false);
|
|
263556
|
-
const { classes: classes2 } = useStyles$
|
|
263628
|
+
const { classes: classes2 } = useStyles$h();
|
|
263557
263629
|
const { classes: selectClasses2 } = useSelectStyles();
|
|
263558
263630
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
263559
263631
|
const filledId = $bdb11010cef70236$export$f680877a34711e37();
|
|
@@ -263575,7 +263647,7 @@ function SpotLayerController(props) {
|
|
|
263575
263647
|
const Visibility = useMemo$1(() => visibleSetting ? VisibilityIcon : VisibilityOffIcon, [visibleSetting]);
|
|
263576
263648
|
const isStaticColor = obsColorEncoding === "spatialLayerColor";
|
|
263577
263649
|
const isColormap = obsColorEncoding === "geneSelection";
|
|
263578
|
-
const { classes: classes2 } = useStyles$
|
|
263650
|
+
const { classes: classes2 } = useStyles$h();
|
|
263579
263651
|
const { classes: lcClasses } = useControllerSectionStyles();
|
|
263580
263652
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
263581
263653
|
const handleVisibleChange = useCallback(() => {
|
|
@@ -263585,7 +263657,7 @@ function SpotLayerController(props) {
|
|
|
263585
263657
|
const handleOpacityChange = useCallback((e3, v) => setOpacity2(v), [setOpacity2]);
|
|
263586
263658
|
return jsx$1(Grid$1, { className: lcClasses.layerControllerGrid, children: jsx$1(Paper, { elevation: 4, className: lcClasses.layerControllerRoot, children: jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsx$1(Grid$1, { size: 1, children: jsx$1(Button, { onClick: handleVisibleChange, className: menuClasses.imageLayerVisibleButton, "aria-label": "Toggle spot layer visibility", children: jsx$1(Visibility, {}) }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(ChannelColorPickerMenu, { theme, color: color2, setColor: setColor2, palette, isStaticColor, isColormap, featureValueColormap, visible }) }), jsx$1(Grid$1, { size: 6, children: jsx$1(Typography, { className: menuClasses.imageLayerName, children: label2 }) }), jsx$1(Grid$1, { size: 2, children: jsx$1(Slider, { value: opacity2, min: 0, max: 1, step: 1e-3, onChange: handleOpacityChange, className: menuClasses.imageLayerOpacitySlider, orientation: "horizontal", "aria-label": `Adjust opacity for layer ${label2}` }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(SpotLayerEllipsisMenu, { filled, setFilled, strokeWidth, setStrokeWidth, featureSelection, obsColorEncoding, setObsColorEncoding, featureValueColormap, setFeatureValueColormap, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(SvgSpots, { className: classes2.layerTypeSpotIcon }) })] }) }) });
|
|
263587
263659
|
}
|
|
263588
|
-
const useStyles$
|
|
263660
|
+
const useStyles$g = makeStyles()(() => ({
|
|
263589
263661
|
layerFeatureControllerGrid: {
|
|
263590
263662
|
padding: "0",
|
|
263591
263663
|
flexWrap: "nowrap"
|
|
@@ -263630,14 +263702,15 @@ function LayerPerFeatureController(props) {
|
|
|
263630
263702
|
]);
|
|
263631
263703
|
}
|
|
263632
263704
|
}, [featureName, featureColor, setFeatureColor, featureColorIndex]);
|
|
263633
|
-
const { classes: classes2 } = useStyles$
|
|
263705
|
+
const { classes: classes2 } = useStyles$g();
|
|
263634
263706
|
const { classes: lcClasses } = useControllerSectionStyles();
|
|
263635
263707
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
263636
263708
|
const [open2, setOpen] = useState(false);
|
|
263637
263709
|
const { colorPickerColor, colorPickerReadable, colorPickerWritable, colorPickerTooltip } = useMemo$1(() => {
|
|
263638
263710
|
if (obsColorEncoding === "geneSelection") {
|
|
263711
|
+
const storedColor = featureColor?.find((fc) => fc.name === featureName)?.color;
|
|
263639
263712
|
return {
|
|
263640
|
-
colorPickerColor:
|
|
263713
|
+
colorPickerColor: storedColor ?? randomByFeatureColor ?? spatialLayerColor,
|
|
263641
263714
|
colorPickerReadable: true,
|
|
263642
263715
|
colorPickerWritable: true,
|
|
263643
263716
|
colorPickerTooltip: null
|
|
@@ -263683,7 +263756,7 @@ function LayerPerFeatureController(props) {
|
|
|
263683
263756
|
]);
|
|
263684
263757
|
return jsx$1(Grid$1, { className: lcClasses.layerControllerGrid, children: jsxs(Paper, { elevation: 2, className: lcClasses.layerControllerSubRow, children: [jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsx$1(Grid$1, { size: 1, children: jsx$1(Button, { onClick: handleRemoveFeature, className: menuClasses.imageLayerVisibleButton, "aria-label": "Remove feature", children: jsx$1(ClearIcon, {}) }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(Tooltip$3, { title: colorPickerTooltip ?? "", disableHoverListener: !colorPickerTooltip, placement: "top", children: jsx$1("span", { children: jsx$1(ChannelColorPickerMenu, { theme, color: colorPickerColor, setColor: colorPickerWritable ? handleColorChange : null, palette, isStaticColor: colorPickerReadable, isColormap: false, featureValueColormap, visible: true }) }) }) }), jsx$1(Grid$1, { size: 6, children: jsx$1(Typography, { className: menuClasses.imageLayerName, children: featureName }) }), jsx$1(Grid$1, { size: 2, sx: { paddingRight: "12px", overflow: "visible" }, children: jsx$1(Slider, { value: opacity2, min: 0, max: 1, step: 1e-3, onChange: handleOpacityChange, className: menuClasses.imageLayerOpacitySlider, orientation: "horizontal", "aria-label": `Adjust opacity for layer ${featureName}` }) }), jsxs(Grid$1, { size: 1, container: true, direction: "row", children: [jsx$1(SvgPoints, { className: classes2.layerTypeFeatureIcon }), null] })] }), loadingDoneFraction < 1 ? jsx$1(Grid$1, { size: 12, container: true, direction: "column", justifyContent: "space-between", className: classes2.layerFeatureControllerGrid, children: jsx$1(LinearProgress, { variant: loadingDoneFraction === 0 ? "indeterminate" : "determinate", value: loadingDoneFraction * 100 }) }) : null] }) }, featureName);
|
|
263685
263758
|
}
|
|
263686
|
-
const useStyles$
|
|
263759
|
+
const useStyles$f = makeStyles()(() => ({
|
|
263687
263760
|
pointLayerButton: {
|
|
263688
263761
|
borderStyle: "dashed",
|
|
263689
263762
|
marginTop: "10px",
|
|
@@ -263712,7 +263785,7 @@ const useStyles$e = makeStyles()(() => ({
|
|
|
263712
263785
|
}
|
|
263713
263786
|
}));
|
|
263714
263787
|
function PointLayerEllipsisMenu(props) {
|
|
263715
|
-
const { featureSelection, featureFilterMode, setFeatureFilterMode, obsColorEncoding, setObsColorEncoding, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible } = props;
|
|
263788
|
+
const { featureSelection, featureFilterMode, setFeatureFilterMode, obsColorEncoding, setObsColorEncoding, featureValueColormap, setFeatureValueColormap, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible } = props;
|
|
263716
263789
|
const [open2, setOpen] = useState(false);
|
|
263717
263790
|
const { classes: selectClasses2 } = useSelectStyles();
|
|
263718
263791
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
@@ -263722,7 +263795,8 @@ function PointLayerEllipsisMenu(props) {
|
|
|
263722
263795
|
const crosshairsVisibleId = $bdb11010cef70236$export$f680877a34711e37();
|
|
263723
263796
|
const legendVisibleId = $bdb11010cef70236$export$f680877a34711e37();
|
|
263724
263797
|
const featureFilterModeId = $bdb11010cef70236$export$f680877a34711e37();
|
|
263725
|
-
|
|
263798
|
+
const colormapSelectorId = $bdb11010cef70236$export$f680877a34711e37();
|
|
263799
|
+
return jsxs(PopperMenu, { open: open2, setOpen, buttonIcon: jsx$1(MoreVertIcon, {}), buttonClassName: menuClasses.imageLayerMenuButton, containerClassName: menuClasses.imageLayerPopperContainer, withPaper: true, getAriaLabel: () => "Open point layer options menu", children: [jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: colormapSelectorId, children: "Colormap: " }), jsx$1(NativeSelect, { onChange: (e3) => setFeatureValueColormap(e3.target.value), value: featureValueColormap, inputProps: { id: colormapSelectorId, "aria-label": "Colormap selector" }, classes: { root: selectClasses2.selectRoot }, children: GLSL_COLORMAPS.map((cmap) => jsx$1("option", { value: cmap, children: cmap }, cmap)) })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: quantitativeColormapId, children: "Color Encoding: " }), jsxs(NativeSelect, { onChange: (e3) => setObsColorEncoding(e3.target.value), value: obsColorEncoding, inputProps: { id: quantitativeColormapId, "aria-label": "Color encoding selector" }, classes: { root: selectClasses2.selectRoot }, children: [jsx$1("option", { value: "spatialLayerColor", children: "Static Color" }), jsx$1("option", { value: "geneSelection", children: "Feature Color" }), jsx$1("option", { value: "randomByFeature", children: "Random Color per Feature" }), jsx$1("option", { value: "random", children: "Random Color per Point" })] })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: featureFilterModeId, children: "Filter to Feature Selection: " }), jsx$1(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" } } })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: colormapRangeId, children: "Colormap Range: " }), jsx$1(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" })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: tooltipsVisibleId, children: "Tooltips Visible: " }), jsx$1(Checkbox$1, { color: "primary", className: menuClasses.menuItemCheckbox, checked: tooltipsVisible, onChange: (e3, v) => setTooltipsVisible(v), slotProps: { input: { id: tooltipsVisibleId, "aria-label": "Toggle tooltip visibility" } } })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: crosshairsVisibleId, children: "Tooltip Crosshairs Visible: " }), jsx$1(Checkbox$1, { color: "primary", className: menuClasses.menuItemCheckbox, checked: tooltipCrosshairsVisible, onChange: (e3, v) => setTooltipCrosshairsVisible(v), slotProps: { input: { id: crosshairsVisibleId, "aria-label": "Toggle tooltip crosshair visibility" } } })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: legendVisibleId, children: "Legend Visible: " }), jsx$1(Checkbox$1, { color: "primary", className: menuClasses.menuItemCheckbox, checked: legendVisible, onChange: (e3, v) => setLegendVisible(v), slotProps: { input: { id: legendVisibleId, "aria-label": "Toggle legend visibility" } } })] })] });
|
|
263726
263800
|
}
|
|
263727
263801
|
function PointLayerController(props) {
|
|
263728
263802
|
const { theme, layerScope, layerCoordination, setLayerCoordination, palette = null, pointMatrixIndicesData, tiledPointsLoadingProgress, layerPerFeatureForPoints } = props;
|
|
@@ -263752,7 +263826,7 @@ function PointLayerController(props) {
|
|
|
263752
263826
|
}, [featureColor, featureSelection]);
|
|
263753
263827
|
const isStaticColor = obsColorEncoding === "spatialLayerColor" || obsColorEncoding === "geneSelection";
|
|
263754
263828
|
const showStaticColor = obsColorEncoding === "spatialLayerColor" || obsColorEncoding === "geneSelection" && hasUnspecifiedFeatureColors;
|
|
263755
|
-
const isColormap =
|
|
263829
|
+
const isColormap = obsColorEncoding === "geneSelection";
|
|
263756
263830
|
const hasSingleSelectedFeature = obsColorEncoding === "geneSelection" && Array.isArray(featureSelection) && featureSelection.length === 1;
|
|
263757
263831
|
const color2 = useMemo$1(() => {
|
|
263758
263832
|
if (showStaticColor) {
|
|
@@ -263799,7 +263873,7 @@ function PointLayerController(props) {
|
|
|
263799
263873
|
featureSelection,
|
|
263800
263874
|
showStaticColor
|
|
263801
263875
|
]);
|
|
263802
|
-
const { classes: classes2 } = useStyles$
|
|
263876
|
+
const { classes: classes2 } = useStyles$f();
|
|
263803
263877
|
const { classes: lcClasses } = useControllerSectionStyles();
|
|
263804
263878
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
263805
263879
|
const handleVisibleChange = useCallback(() => {
|
|
@@ -263811,9 +263885,24 @@ function PointLayerController(props) {
|
|
|
263811
263885
|
const [coloringTabIndex, setColoringTabIndex] = useState(0);
|
|
263812
263886
|
const { featureIndex } = pointMatrixIndicesData || {};
|
|
263813
263887
|
const hasSelectedFeatures = Array.isArray(featureSelection) && featureSelection.length > 0;
|
|
263814
|
-
|
|
263888
|
+
useEffect(() => {
|
|
263889
|
+
if (obsColorEncoding !== "geneSelection" || !Array.isArray(featureSelection))
|
|
263890
|
+
return;
|
|
263891
|
+
const cleanedFeatureColor = (featureColor ?? []).filter((fc) => featureSelection.includes(fc.name));
|
|
263892
|
+
const missingEntries = featureSelection.filter((featureName) => !cleanedFeatureColor.find((fc) => fc.name === featureName)).map((featureName) => {
|
|
263893
|
+
const varIdx = featureIndex?.indexOf(featureName) ?? -1;
|
|
263894
|
+
const fColor = varIdx >= 0 ? PALETTE[varIdx % PALETTE.length] : getDefaultColor(theme);
|
|
263895
|
+
return { name: featureName, color: fColor };
|
|
263896
|
+
});
|
|
263897
|
+
const nextFeatureColor = [...cleanedFeatureColor, ...missingEntries];
|
|
263898
|
+
const changed = nextFeatureColor.length !== featureColor?.length || missingEntries.length > 0;
|
|
263899
|
+
if (changed) {
|
|
263900
|
+
setFeatureColor(nextFeatureColor);
|
|
263901
|
+
}
|
|
263902
|
+
}, [featureSelection, obsColorEncoding, featureIndex, featureColor]);
|
|
263903
|
+
return jsxs(Grid$1, { className: lcClasses.layerControllerGrid, children: [jsxs(Paper, { elevation: 4, className: lcClasses.layerControllerRoot, children: [jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsx$1(Grid$1, { size: 1, children: jsx$1(Button, { onClick: handleVisibleChange, className: menuClasses.imageLayerVisibleButton, "aria-label": "Toggle layer visibility", children: jsx$1(Visibility, {}) }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(ChannelColorPickerMenu, { theme, color: color2, setColor: setColor2, palette, isStaticColor, isColormap, featureValueColormap, visible }) }), jsx$1(Grid$1, { size: 6, children: jsx$1(Typography, { className: menuClasses.imageLayerName, children: label2 }) }), jsx$1(Grid$1, { size: 2, children: jsx$1(Slider, { value: opacity2, min: 0, max: 1, step: 1e-3, onChange: handleOpacityChange, className: menuClasses.imageLayerOpacitySlider, orientation: "horizontal", "aria-label": `Adjust opacity for layer ${label2}` }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(PointLayerEllipsisMenu, { featureSelection, obsColorEncoding, setObsColorEncoding, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible, featureFilterMode, setFeatureFilterMode, featureValueColormap, setFeatureValueColormap }) }), jsxs(Grid$1, { size: 1, container: true, direction: "row", children: [jsx$1(SvgPoints, { className: classes2.layerTypePointIcon }), null] })] }), loadingDoneFraction < 1 ? jsx$1(Grid$1, { size: 12, container: true, direction: "column", justifyContent: "space-between", className: classes2.pointFeatureControllerGrid, children: jsx$1(LinearProgress, { variant: loadingDoneFraction === 0 ? "indeterminate" : "determinate", value: loadingDoneFraction * 100 }) }) : null, null] }), layerPerFeatureForPoints && hasSelectedFeatures ? jsxs(Fragment, { children: [featureSelection.map((featureName) => jsx$1(LayerPerFeatureController, { theme, featureName, featureColor, setFeatureColor, spatialLayerColor, featureIndex, featureValueColormap, featureSelection, setFeatureSelection, obsColorEncoding, loadingDoneFraction, opacity: opacity2, handleOpacityChange }, featureName)), jsx$1(Grid$1, { className: lcClasses.layerControllerGrid, children: jsx$1(Paper, { elevation: 2, className: lcClasses.layerControllerSubRow, children: jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsx$1(Grid$1, { size: 1, children: jsx$1(Button, { onClick: () => setFeatureFilterMode(featureFilterMode === "featureSelection" ? null : "featureSelection"), className: menuClasses.imageLayerVisibleButton, "aria-label": "Toggle visibility of unselected points", children: featureFilterMode === "featureSelection" ? jsx$1(VisibilityOffIcon, {}) : jsx$1(VisibilityIcon, {}) }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(ChannelColorPickerMenu, { theme, color: getDefaultColor("dark"), setColor: null, isStaticColor: true, isColormap: false, visible: true }) }), jsx$1(Grid$1, { size: 6, children: jsx$1(Typography, { className: menuClasses.imageLayerName, children: "Unselected" }) }), jsx$1(Grid$1, { size: 2, sx: { paddingRight: "12px", overflow: "visible" }, children: jsx$1(Slider, { value: opacity2, min: 0, max: 1, step: 1e-3, onChange: handleOpacityChange, className: menuClasses.imageLayerOpacitySlider, orientation: "horizontal", "aria-label": "Adjust opacity for unselected layer" }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(SvgPoints, { className: classes2.layerTypePointIcon }) })] }) }) })] }) : null] });
|
|
263815
263904
|
}
|
|
263816
|
-
const useStyles$
|
|
263905
|
+
const useStyles$e = makeStyles()(() => ({
|
|
263817
263906
|
layerTypeSegmentationIcon: {
|
|
263818
263907
|
height: "100%",
|
|
263819
263908
|
marginLeft: "1px",
|
|
@@ -263826,7 +263915,7 @@ const useStyles$d = makeStyles()(() => ({
|
|
|
263826
263915
|
function SegmentationChannelEllipsisMenu(props) {
|
|
263827
263916
|
const { obsType, featureType, featureValueType, strokeWidth, setStrokeWidth, filled, setFilled, featureSelection, obsColorEncoding, setObsColorEncoding, featureValueColormap, setFeatureValueColormap, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible } = props;
|
|
263828
263917
|
const [open2, setOpen] = useState(false);
|
|
263829
|
-
const { classes: classes2 } = useStyles$
|
|
263918
|
+
const { classes: classes2 } = useStyles$e();
|
|
263830
263919
|
const { classes: selectClasses2 } = useSelectStyles();
|
|
263831
263920
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
263832
263921
|
const filledId = $bdb11010cef70236$export$f680877a34711e37();
|
|
@@ -263845,7 +263934,7 @@ function SegmentationChannelController(props) {
|
|
|
263845
263934
|
const Visibility = useMemo$1(() => visibleSetting ? VisibilityIcon : VisibilityOffIcon, [visibleSetting]);
|
|
263846
263935
|
const isStaticColor = obsColorEncoding === "spatialChannelColor";
|
|
263847
263936
|
const isColormap = obsColorEncoding === "geneSelection";
|
|
263848
|
-
const { classes: classes2 } = useStyles$
|
|
263937
|
+
const { classes: classes2 } = useStyles$e();
|
|
263849
263938
|
const { classes: lcClasses } = useControllerSectionStyles();
|
|
263850
263939
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
263851
263940
|
const handleVisibleChange = useCallback(() => {
|
|
@@ -265086,7 +265175,7 @@ function useBaseQuery(options, Observer, queryClient) {
|
|
|
265086
265175
|
function useQuery(options, queryClient) {
|
|
265087
265176
|
return useBaseQuery(options, QueryObserver);
|
|
265088
265177
|
}
|
|
265089
|
-
const useStyles$
|
|
265178
|
+
const useStyles$d = makeStyles()(() => ({
|
|
265090
265179
|
channelMenuButton: {
|
|
265091
265180
|
backgroundColor: "transparent",
|
|
265092
265181
|
padding: "3px 0",
|
|
@@ -265100,7 +265189,7 @@ const useStyles$c = makeStyles()(() => ({
|
|
|
265100
265189
|
function ChannelOptions(props) {
|
|
265101
265190
|
const { onRemove: onRemove2, onResetWindowUsingIQR, showValueExtent, setShowValueExtent, numResolutions, spatialMaxResolution, setSpatialMaxResolution } = props;
|
|
265102
265191
|
const [open2, setOpen] = useState(false);
|
|
265103
|
-
const { classes: classes2 } = useStyles$
|
|
265192
|
+
const { classes: classes2 } = useStyles$d();
|
|
265104
265193
|
const { classes: selectClasses2 } = useSelectStyles();
|
|
265105
265194
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
265106
265195
|
function handleRemove() {
|
|
@@ -265113,7 +265202,7 @@ function ChannelOptions(props) {
|
|
|
265113
265202
|
const domainTypeId = $bdb11010cef70236$export$f680877a34711e37();
|
|
265114
265203
|
return jsxs(PopperMenu, { open: open2, setOpen, buttonIcon: jsx$1(MoreVertIcon, { fontSize: "small" }), buttonClassName: classes2.channelMenuButton, containerClassName: menuClasses.imageLayerPopperContainer, placement: "bottom-end", withPaper: true, "aria-label": "Open channel options menu", children: [jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: domainTypeId, children: "Best Resolution: " }), jsx$1(Slider, { value: spatialMaxResolution || 1, valueLabelDisplay: "auto", onChange: (e3, v) => setSpatialMaxResolution(v), min: 1, max: numResolutions - 1, step: 1, orientation: "horizontal" })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: domainTypeId, children: "Slider Extent: " }), jsxs(NativeSelect, { onChange: handleDomainTypeChange, value: showValueExtent ? "Value Min/Max" : "Dtype Min/Max", inputProps: { id: domainTypeId, "aria-label": "Slider extent selector" }, classes: { root: selectClasses2.selectRoot }, children: [jsx$1("option", { value: "Value Min/Max", children: "Value Min/Max" }), jsx$1("option", { value: "Dtype Min/Max", children: "Dtype Min/Max" })] })] }), jsx$1(MenuItem, { dense: true, disableGutters: true, component: "button", onClick: onResetWindowUsingIQR, className: classes2.menuItemButton, "aria-label": "Click to use IQR for channel", children: "Reset window using IQR" }), jsx$1(MenuItem, { dense: true, disableGutters: true, component: "button", onClick: handleRemove, className: classes2.menuItemButton, "aria-label": "Click to remove channel", children: "Remove channel" })] });
|
|
265115
265204
|
}
|
|
265116
|
-
const useStyles$
|
|
265205
|
+
const useStyles$c = makeStyles()(() => ({
|
|
265117
265206
|
channelSlider: {
|
|
265118
265207
|
marginTop: "7px"
|
|
265119
265208
|
}
|
|
@@ -265123,7 +265212,7 @@ function ChannelSlider(props) {
|
|
|
265123
265212
|
const rgbColor = toRgbUIString(colormapOn, color2, theme);
|
|
265124
265213
|
const dtype = image2?.getDtype();
|
|
265125
265214
|
const fullDomain = dtype ? DOMAINS[dtype] : [0, 0];
|
|
265126
|
-
const { classes: classes2 } = useStyles$
|
|
265215
|
+
const { classes: classes2 } = useStyles$c();
|
|
265127
265216
|
useEffect(() => {
|
|
265128
265217
|
if (!window2 && !disabled && Array.isArray(minMaxDomain)) {
|
|
265129
265218
|
setWindow2(minMaxDomain);
|
|
@@ -265138,7 +265227,7 @@ function ChannelSlider(props) {
|
|
|
265138
265227
|
return `${labelPrefix} for ${rgbColor} colormap channel`;
|
|
265139
265228
|
}, getAriaValueText: () => `Current colormap values: ${rgbColor}-${window2}`, min: min2, max: max2, step, orientation: "horizontal", className: classes2.channelSlider, style: { color: rgbColor }, disabled });
|
|
265140
265229
|
}
|
|
265141
|
-
const useStyles$
|
|
265230
|
+
const useStyles$b = makeStyles()(() => ({
|
|
265142
265231
|
visibilityCheckbox: {
|
|
265143
265232
|
padding: "10px 0"
|
|
265144
265233
|
}
|
|
@@ -265152,10 +265241,10 @@ function getCheckboxColor(colormapOn, color2, theme) {
|
|
|
265152
265241
|
function ChannelVisibilityCheckbox(props) {
|
|
265153
265242
|
const { color: color2, visible, setVisible, disabled, theme, colormapOn } = props;
|
|
265154
265243
|
const rgbColor = getCheckboxColor(colormapOn, color2, theme);
|
|
265155
|
-
const { classes: classes2 } = useStyles$
|
|
265244
|
+
const { classes: classes2 } = useStyles$b();
|
|
265156
265245
|
return jsx$1(Checkbox$1, { onChange: (e3, v) => setVisible(v), checked: visible, disabled, className: classes2.visibilityCheckbox, style: { color: rgbColor, "&$checked": { color: rgbColor } }, slotProps: { input: { "aria-label": "Toggle channel visibility" } } });
|
|
265157
265246
|
}
|
|
265158
|
-
const useStyles$
|
|
265247
|
+
const useStyles$a = makeStyles()(() => ({
|
|
265159
265248
|
oneLineChannelSelect: {
|
|
265160
265249
|
width: "90%",
|
|
265161
265250
|
marginLeft: "5%",
|
|
@@ -265163,17 +265252,23 @@ const useStyles$9 = makeStyles()(() => ({
|
|
|
265163
265252
|
}
|
|
265164
265253
|
}));
|
|
265165
265254
|
function ChannelSelectionDropdown(props) {
|
|
265166
|
-
const { featureIndex, targetC, setTargetC, setWindow: setWindow2, disabled } = props;
|
|
265167
|
-
const { classes: classes2 } = useStyles$
|
|
265255
|
+
const { featureIndex, channelsSortOrder, targetC, setTargetC, setWindow: setWindow2, disabled } = props;
|
|
265256
|
+
const { classes: classes2 } = useStyles$a();
|
|
265168
265257
|
const { classes: selectClasses2 } = useSelectStyles();
|
|
265169
265258
|
function handleChange(event2) {
|
|
265170
265259
|
setTargetC(event2.target.value === "" ? null : Number(event2.target.value));
|
|
265171
265260
|
setWindow2(null);
|
|
265172
265261
|
}
|
|
265173
|
-
|
|
265174
|
-
|
|
265175
|
-
|
|
265176
|
-
|
|
265262
|
+
const sortedOptions = useMemo$1(() => {
|
|
265263
|
+
if (!Array.isArray(featureIndex))
|
|
265264
|
+
return [];
|
|
265265
|
+
const options = featureIndex.map((channelName, channelIndex) => ({ channelName, channelIndex }));
|
|
265266
|
+
if (channelsSortOrder === "alphabetical") {
|
|
265267
|
+
return options.sort((a2, b2) => a2.channelName.localeCompare(b2.channelName, void 0, { numeric: true, sensitivity: "base" }));
|
|
265268
|
+
}
|
|
265269
|
+
return options;
|
|
265270
|
+
}, [featureIndex, channelsSortOrder]);
|
|
265271
|
+
return Array.isArray(featureIndex) ? jsx$1(NativeSelect, { classes: { root: selectClasses2.selectRoot }, className: classes2.oneLineChannelSelect, value: targetC === null ? "" : targetC, onChange: handleChange, inputProps: { "aria-label": "Channel selector" }, children: sortedOptions.map(({ channelName, channelIndex }) => jsx$1("option", { disabled, value: channelIndex, children: channelName }, `${channelName}-${channelIndex}`)) }) : null;
|
|
265177
265272
|
}
|
|
265178
265273
|
function ImageChannelController(props) {
|
|
265179
265274
|
const {
|
|
@@ -265201,7 +265296,8 @@ function ImageChannelController(props) {
|
|
|
265201
265296
|
spatialRenderingMode,
|
|
265202
265297
|
numResolutions,
|
|
265203
265298
|
spatialMaxResolution,
|
|
265204
|
-
setSpatialMaxResolution
|
|
265299
|
+
setSpatialMaxResolution,
|
|
265300
|
+
channelsSortOrder
|
|
265205
265301
|
} = props;
|
|
265206
265302
|
const removeChannel = useRemoveImageChannelInMetaCoordinationScopes();
|
|
265207
265303
|
const [showValueExtent, setShowValueExtent] = useState(true);
|
|
@@ -265238,7 +265334,7 @@ function ImageChannelController(props) {
|
|
|
265238
265334
|
setWindow2(minMaxDomain);
|
|
265239
265335
|
}
|
|
265240
265336
|
}
|
|
265241
|
-
return jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsx$1(Grid$1, { size: 1, children: jsx$1(ChannelVisibilityCheckbox, { color: color2, setColor: setColor2, visible, setVisible, disabled: isLoading, theme, colormapOn }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(ChannelColorPickerMenu, { color: color2, setColor: setColor2, visible, setVisible, disabled: isLoading, theme, isStaticColor: !colormapOn, palette: VIEWER_PALETTE }) }), jsx$1(Grid$1, { size: 6, children: jsx$1(ChannelSelectionDropdown, { featureIndex, targetC, setTargetC, setWindow: setWindow2, disabled: isLoading }) }), jsx$1(Grid$1, { size: 3, children: jsx$1(ChannelSlider, { image: image2, targetT, targetZ, targetC, window: window2, setWindow: setWindow2, disabled, color: color2, theme, colormapOn, showValueExtent, minMaxDomain }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(ChannelOptions, { onRemove: onRemove2, showValueExtent, setShowValueExtent, onResetWindowUsingIQR: handleResetWindowUsingIQR, numResolutions, spatialMaxResolution, setSpatialMaxResolution }) })] });
|
|
265337
|
+
return jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsx$1(Grid$1, { size: 1, children: jsx$1(ChannelVisibilityCheckbox, { color: color2, setColor: setColor2, visible, setVisible, disabled: isLoading, theme, colormapOn }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(ChannelColorPickerMenu, { color: color2, setColor: setColor2, visible, setVisible, disabled: isLoading, theme, isStaticColor: !colormapOn, palette: VIEWER_PALETTE }) }), jsx$1(Grid$1, { size: 6, children: jsx$1(ChannelSelectionDropdown, { featureIndex, targetC, setTargetC, setWindow: setWindow2, disabled: isLoading, channelsSortOrder }) }), jsx$1(Grid$1, { size: 3, children: jsx$1(ChannelSlider, { image: image2, targetT, targetZ, targetC, window: window2, setWindow: setWindow2, disabled, color: color2, theme, colormapOn, showValueExtent, minMaxDomain }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(ChannelOptions, { onRemove: onRemove2, showValueExtent, setShowValueExtent, onResetWindowUsingIQR: handleResetWindowUsingIQR, numResolutions, spatialMaxResolution, setSpatialMaxResolution }) })] });
|
|
265242
265338
|
}
|
|
265243
265339
|
function DimensionSlider(props) {
|
|
265244
265340
|
const { boundingSlice, sliceValue, setSliceValue, label: label2 } = props;
|
|
@@ -265292,7 +265388,7 @@ function LoadingStatusIndicator(props) {
|
|
|
265292
265388
|
}
|
|
265293
265389
|
return jsxs(Grid$1, { container: true, px: 0.5, children: [jsx$1(Grid$1, { size: 6, alignItems: "start", children: jsx$1(Grid$1, { container: true, alignItems: "center", gap: 1, children: statusColor !== "success" ? jsx$1(StatusChip, { label: statusLabel, color: statusColor, size: "small" }) : null }) }), jsx$1(Grid$1, { size: 6, px: 1, my: 0.25, children: jsx$1(LoadingText, { bricksLoaded, currentRequestCount, totalBricksRequested, isLoading }) }), jsx$1(Grid$1, { size: 12, children: jsxs(Grid$1, { container: true, direction: "row", spacing: 2, alignItems: "center", wrap: "nowrap", children: [jsx$1(LoadingControlButton, { startIcon: jsx$1(Stop, {}), onClick: onStopLoading, disabled: noNewRequests, ariaLabel: "Stop loading data and render at highest resolution", children: "Stop Loading" }), jsx$1(LoadingControlButton, { startIcon: jsx$1(Replay, {}), onClick: onRestartLoading, disabled: !noNewRequests && !isLoading, ariaLabel: "Restart data loading", children: "Restart Loading" })] }) }), jsx$1(Grid$1, { size: 12, visibility: isLoading ? "visible" : "hidden", mt: 1, mb: 0.5, children: jsx$1(LinearProgress, { variant: "determinate", value: percentage }) })] });
|
|
265294
265390
|
}
|
|
265295
|
-
const useStyles$
|
|
265391
|
+
const useStyles$9 = makeStyles()(() => ({
|
|
265296
265392
|
imageLayerButton: {
|
|
265297
265393
|
borderStyle: "dashed",
|
|
265298
265394
|
marginTop: "10px",
|
|
@@ -265337,7 +265433,7 @@ const lodSliderRangeConfig = {
|
|
|
265337
265433
|
step: 1
|
|
265338
265434
|
};
|
|
265339
265435
|
function ImageLayerEllipsisMenu(props) {
|
|
265340
|
-
const { colormap, setColormap, photometricInterpretation, setPhotometricInterpretation, spatialTargetResolution, setSpatialTargetResolution, spatialLodFactor, setSpatialLodFactor, volumetricRenderingAlgorithm, setVolumetricRenderingAlgorithm, spatialLayerTransparentColor, setSpatialLayerTransparentColor, spatialRenderingMode, image: image2, channelScopes, tooltipsVisible, setTooltipsVisible, channelLabelsVisible, setChannelLabelsVisible, channelLabelsOrientation, setChannelLabelsOrientation, channelLabelSize, setChannelLabelSize } = props;
|
|
265436
|
+
const { colormap, setColormap, photometricInterpretation, setPhotometricInterpretation, spatialTargetResolution, setSpatialTargetResolution, spatialLodFactor, setSpatialLodFactor, volumetricRenderingAlgorithm, setVolumetricRenderingAlgorithm, spatialLayerTransparentColor, setSpatialLayerTransparentColor, spatialRenderingMode, image: image2, channelScopes, tooltipsVisible, setTooltipsVisible, channelLabelsVisible, setChannelLabelsVisible, channelLabelsOrientation, setChannelLabelsOrientation, channelLabelSize, setChannelLabelSize, channelsSortOrder, setChannelsSortOrder } = props;
|
|
265341
265437
|
const [open2, setOpen] = useState(false);
|
|
265342
265438
|
const { classes: selectClasses2 } = useSelectStyles();
|
|
265343
265439
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
@@ -265363,6 +265459,9 @@ function ImageLayerEllipsisMenu(props) {
|
|
|
265363
265459
|
function handleChannelLabelsOrientationChange(event2) {
|
|
265364
265460
|
setChannelLabelsOrientation(event2.target.value);
|
|
265365
265461
|
}
|
|
265462
|
+
function handleChannelsSortOrderChange(event2) {
|
|
265463
|
+
setChannelsSortOrder(event2.target.value);
|
|
265464
|
+
}
|
|
265366
265465
|
function handleLodFactorChange(event2, value2) {
|
|
265367
265466
|
setLocalLodSliderValue(value2);
|
|
265368
265467
|
}
|
|
@@ -265384,11 +265483,12 @@ function ImageLayerEllipsisMenu(props) {
|
|
|
265384
265483
|
const channelLabelsOrientationId = $bdb11010cef70236$export$f680877a34711e37();
|
|
265385
265484
|
const channelLabelSizeId = $bdb11010cef70236$export$f680877a34711e37();
|
|
265386
265485
|
const lodFactorId = $bdb11010cef70236$export$f680877a34711e37();
|
|
265486
|
+
const channelsSortOrderId = $bdb11010cef70236$export$f680877a34711e37();
|
|
265387
265487
|
return jsxs(PopperMenu, { open: open2, setOpen, buttonIcon: jsx$1(MoreVertIcon, {}), buttonClassName: menuClasses.imageLayerMenuButton, containerClassName: menuClasses.imageLayerPopperContainer, withPaper: true, "aria-label": "Open image layer options menu", children: [is3dMode && jsxs(MenuItem, { dense: true, disableGutters: true, className: menuClasses.menuItem, children: [jsx$1("label", { id: `${lodFactorId}-label`, className: menuClasses.imageLayerMenuLabel, htmlFor: lodFactorId, children: "LOD Factor: " }), jsx$1(Slider, { disabled: !is3dMode, value: localLodSliderValue, onChange: handleLodFactorChange, onChangeCommitted: handleLodFactorChangeCommitted, className: menuClasses.menuItemSlider, orientation: "horizontal", id: lodFactorId, "aria-label": "Level of detail factor slider", valueLabelDisplay: "off", ...lodSliderRangeConfig }), jsx$1(Box, { px: 1 }), jsx$1(Input$1, { value: localLodSliderValue, onChange: handleLodFactorInputChange, onBlur: handleLodFactorInputChange, "aria-labelledby": `${lodFactorId}-label`, size: "small", sx: { width: "6ch", flexShrink: 0, fontVariantNumeric: "tabular-nums" }, endAdornment: jsx$1(InputAdornment$1, { position: "end", variant: "standard", sx: { "& > p": { marginBottom: 0 } }, children: "%" }), inputProps: {
|
|
265388
265488
|
...lodSliderRangeConfig,
|
|
265389
265489
|
inputMode: "numeric",
|
|
265390
265490
|
pattern: "[0-9]*"
|
|
265391
|
-
} })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: colormapId, children: "Colormap: " }), jsxs(NativeSelect, { disabled: photometricInterpretation === "RGB", onChange: handleColormapChange, value: colormap === null ? "" : colormap, inputProps: { id: colormapId, "aria-label": "Colormap selector" }, classes: { root: selectClasses2.selectRoot }, children: [jsx$1("option", { "aria-label": "None", value: "", children: "None" }), COLORMAP_OPTIONS.map((name2) => jsx$1("option", { value: name2, children: name2 }, name2))] })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: interpretationId, children: "Photometric Interpretation: " }), jsxs(NativeSelect, { onChange: handleInterpretationChange, value: photometricInterpretation, inputProps: { id: interpretationId, "aria-label": "Photometric interpretation selector" }, classes: { root: selectClasses2.selectRoot }, children: [jsx$1("option", { "aria-label": "RGB", value: "RGB", children: "RGB" }), channelScopes.length > 0 ? jsx$1("option", { "aria-label": "BlackIsZero", value: "BlackIsZero", children: "BlackIsZero" }) : null] })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: transparentId, children: "Zero Transparent: " }), jsx$1(Checkbox$1, { color: "primary", checked: spatialLayerTransparentColor !== null, onChange: (e3, v) => setSpatialLayerTransparentColor(v ? [0, 0, 0] : null), slotProps: { input: { id: transparentId, "aria-label": "Render zero-value pixels as transparent" } } })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: volumetricId, children: "Volumetric Rendering: " }), jsxs(NativeSelect, { onChange: handleVolumetricChange, value: volumetricRenderingAlgorithm, inputProps: { id: volumetricId, "aria-label": "Volumetric rendering algorithm selector" }, classes: { root: selectClasses2.selectRoot }, disabled: !is3dMode, children: [jsx$1("option", { "aria-label": "Additive", value: "additive", children: "Additive" }), jsx$1("option", { "aria-label": "Maximum Intensity Projection", value: "maximumIntensityProjection", children: "Maximum Intensity Projection" })] })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: resolutionId, children: "Volume Resolution: " }), jsxs(NativeSelect, { disabled: !is3dMode || !isMultiResolution, onChange: handleResolutionChange, value: spatialTargetResolution === null ? "auto" : spatialTargetResolution, inputProps: { id: resolutionId, "aria-label": "Volumetric resolution selector" }, classes: { root: selectClasses2.selectRoot }, children: [jsx$1("option", { value: "auto", children: "Auto" }), Array.isArray(multiResolutionStats) ? multiResolutionStats.map((stats, resolution) => stats.canLoad ? jsx$1("option", { value: resolution, children: `3D: ${resolution}x Downsampled, ~${formatBytes(stats.totalBytes)} per channel, (${stats.height}, ${stats.width}, ${stats.depthDownsampled})` }, `(${stats.height}, ${stats.width}, ${stats.depthDownsampled})`) : null) : null] })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: tooltipsVisibleId, children: "Tooltips Visible: " }), jsx$1(Checkbox$1, { color: "primary", checked: tooltipsVisible, onChange: (e3, v) => setTooltipsVisible(v), slotProps: { input: { id: tooltipsVisibleId, "aria-label": "Render pixel value tooltips" } } })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: channelLabelsVisibleId, children: "Channel Labels Visible: " }), jsx$1(Checkbox$1, { disabled: photometricInterpretation === "RGB", color: "primary", checked: channelLabelsVisible, onChange: (e3, v) => setChannelLabelsVisible(v), slotProps: { input: { id: channelLabelsVisibleId, "aria-label": "Render channel labels" } } })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: channelLabelsOrientationId, children: "Channel Labels Orientation: " }), jsxs(NativeSelect, { disabled: photometricInterpretation === "RGB", onChange: handleChannelLabelsOrientationChange, value: channelLabelsOrientation, inputProps: { id: channelLabelsOrientationId, "aria-label": "Channel labels orientation selector" }, classes: { root: selectClasses2.selectRoot }, children: [jsx$1("option", { "aria-label": "Vertical", value: "vertical", children: "Vertical" }), jsx$1("option", { "aria-label": "Horizontal", value: "horizontal", children: "Horizontal" })] })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: channelLabelSizeId, children: "Channel Labels Size: " }), jsx$1(Slider, { disabled: photometricInterpretation === "RGB", value: channelLabelSize, min: 8, max: 36, step: 1, onChange: (e3, v) => setChannelLabelSize(v), className: menuClasses.menuItemSlider, orientation: "horizontal", id: channelLabelSizeId, "aria-label": "Channel labels text size slider" })] })] });
|
|
265491
|
+
} })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: colormapId, children: "Colormap: " }), jsxs(NativeSelect, { disabled: photometricInterpretation === "RGB", onChange: handleColormapChange, value: colormap === null ? "" : colormap, inputProps: { id: colormapId, "aria-label": "Colormap selector" }, classes: { root: selectClasses2.selectRoot }, children: [jsx$1("option", { "aria-label": "None", value: "", children: "None" }), COLORMAP_OPTIONS.map((name2) => jsx$1("option", { value: name2, children: name2 }, name2))] })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: interpretationId, children: "Photometric Interpretation: " }), jsxs(NativeSelect, { onChange: handleInterpretationChange, value: photometricInterpretation, inputProps: { id: interpretationId, "aria-label": "Photometric interpretation selector" }, classes: { root: selectClasses2.selectRoot }, children: [jsx$1("option", { "aria-label": "RGB", value: "RGB", children: "RGB" }), channelScopes.length > 0 ? jsx$1("option", { "aria-label": "BlackIsZero", value: "BlackIsZero", children: "BlackIsZero" }) : null] })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: transparentId, children: "Zero Transparent: " }), jsx$1(Checkbox$1, { color: "primary", checked: spatialLayerTransparentColor !== null, onChange: (e3, v) => setSpatialLayerTransparentColor(v ? [0, 0, 0] : null), slotProps: { input: { id: transparentId, "aria-label": "Render zero-value pixels as transparent" } } })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: volumetricId, children: "Volumetric Rendering: " }), jsxs(NativeSelect, { onChange: handleVolumetricChange, value: volumetricRenderingAlgorithm, inputProps: { id: volumetricId, "aria-label": "Volumetric rendering algorithm selector" }, classes: { root: selectClasses2.selectRoot }, disabled: !is3dMode, children: [jsx$1("option", { "aria-label": "Additive", value: "additive", children: "Additive" }), jsx$1("option", { "aria-label": "Maximum Intensity Projection", value: "maximumIntensityProjection", children: "Maximum Intensity Projection" })] })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: resolutionId, children: "Volume Resolution: " }), jsxs(NativeSelect, { disabled: !is3dMode || !isMultiResolution, onChange: handleResolutionChange, value: spatialTargetResolution === null ? "auto" : spatialTargetResolution, inputProps: { id: resolutionId, "aria-label": "Volumetric resolution selector" }, classes: { root: selectClasses2.selectRoot }, children: [jsx$1("option", { value: "auto", children: "Auto" }), Array.isArray(multiResolutionStats) ? multiResolutionStats.map((stats, resolution) => stats.canLoad ? jsx$1("option", { value: resolution, children: `3D: ${resolution}x Downsampled, ~${formatBytes(stats.totalBytes)} per channel, (${stats.height}, ${stats.width}, ${stats.depthDownsampled})` }, `(${stats.height}, ${stats.width}, ${stats.depthDownsampled})`) : null) : null] })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: tooltipsVisibleId, children: "Tooltips Visible: " }), jsx$1(Checkbox$1, { color: "primary", checked: tooltipsVisible, onChange: (e3, v) => setTooltipsVisible(v), slotProps: { input: { id: tooltipsVisibleId, "aria-label": "Render pixel value tooltips" } } })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: channelLabelsVisibleId, children: "Channel Labels Visible: " }), jsx$1(Checkbox$1, { disabled: photometricInterpretation === "RGB", color: "primary", checked: channelLabelsVisible, onChange: (e3, v) => setChannelLabelsVisible(v), slotProps: { input: { id: channelLabelsVisibleId, "aria-label": "Render channel labels" } } })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: channelLabelsOrientationId, children: "Channel Labels Orientation: " }), jsxs(NativeSelect, { disabled: photometricInterpretation === "RGB", onChange: handleChannelLabelsOrientationChange, value: channelLabelsOrientation, inputProps: { id: channelLabelsOrientationId, "aria-label": "Channel labels orientation selector" }, classes: { root: selectClasses2.selectRoot }, children: [jsx$1("option", { "aria-label": "Vertical", value: "vertical", children: "Vertical" }), jsx$1("option", { "aria-label": "Horizontal", value: "horizontal", children: "Horizontal" })] })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: channelLabelSizeId, children: "Channel Labels Size: " }), jsx$1(Slider, { disabled: photometricInterpretation === "RGB", value: channelLabelSize, min: 8, max: 36, step: 1, onChange: (e3, v) => setChannelLabelSize(v), className: menuClasses.menuItemSlider, orientation: "horizontal", id: channelLabelSizeId, "aria-label": "Channel labels text size slider" })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: channelsSortOrderId, children: "Channel Ordering: " }), jsxs(NativeSelect, { onChange: handleChannelsSortOrderChange, value: channelsSortOrder, inputProps: { id: channelsSortOrderId, "aria-label": "Channel sort order selector" }, classes: { root: selectClasses2.selectRoot }, children: [jsx$1("option", { "aria-label": "Original", value: "original", children: "Original" }), jsx$1("option", { "aria-label": "Alphabetical", value: "alphabetical", children: "Alphabetical" })] })] })] });
|
|
265392
265492
|
}
|
|
265393
265493
|
function ImageLayerController(props) {
|
|
265394
265494
|
const {
|
|
@@ -265414,8 +265514,8 @@ function ImageLayerController(props) {
|
|
|
265414
265514
|
volumeStillRef = null
|
|
265415
265515
|
} = props;
|
|
265416
265516
|
const [open2, setOpen] = useState(true);
|
|
265417
|
-
const { spatialLayerVisible: visible, spatialLayerOpacity: opacity2, spatialLayerColormap: colormap, photometricInterpretation, spatialTargetResolution, spatialLodFactor, volumetricRenderingAlgorithm, spatialLayerTransparentColor, spatialSliceX, spatialSliceY, spatialSliceZ, tooltipsVisible, spatialChannelLabelsVisible: channelLabelsVisible, spatialChannelLabelsOrientation: channelLabelsOrientation, spatialChannelLabelSize: channelLabelSize } = layerCoordination;
|
|
265418
|
-
const { setSpatialLayerVisible: setVisible, setSpatialLayerOpacity: setOpacity2, setSpatialLayerColormap: setColormap, setPhotometricInterpretation, setSpatialTargetResolution, setSpatialLodFactor, setVolumetricRenderingAlgorithm, setSpatialLayerTransparentColor, setSpatialSliceX, setSpatialSliceY, setSpatialSliceZ, setTooltipsVisible, setSpatialChannelLabelsVisible: setChannelLabelsVisible, setSpatialChannelLabelsOrientation: setChannelLabelsOrientation, setSpatialChannelLabelSize: setChannelLabelSize } = setLayerCoordination;
|
|
265517
|
+
const { spatialLayerVisible: visible, spatialLayerOpacity: opacity2, spatialLayerColormap: colormap, photometricInterpretation, spatialTargetResolution, spatialLodFactor, volumetricRenderingAlgorithm, spatialLayerTransparentColor, spatialSliceX, spatialSliceY, spatialSliceZ, tooltipsVisible, spatialChannelLabelsVisible: channelLabelsVisible, spatialChannelLabelsOrientation: channelLabelsOrientation, spatialChannelLabelSize: channelLabelSize, spatialChannelsSortOrder: channelsSortOrder } = layerCoordination;
|
|
265518
|
+
const { setSpatialLayerVisible: setVisible, setSpatialLayerOpacity: setOpacity2, setSpatialLayerColormap: setColormap, setPhotometricInterpretation, setSpatialTargetResolution, setSpatialLodFactor, setVolumetricRenderingAlgorithm, setSpatialLayerTransparentColor, setSpatialSliceX, setSpatialSliceY, setSpatialSliceZ, setTooltipsVisible, setSpatialChannelLabelsVisible: setChannelLabelsVisible, setSpatialChannelLabelsOrientation: setChannelLabelsOrientation, setSpatialChannelLabelSize: setChannelLabelSize, setSpatialChannelsSortOrder: setChannelsSortOrder } = setLayerCoordination;
|
|
265419
265519
|
const addChannel = useAddImageChannelInMetaCoordinationScopes();
|
|
265420
265520
|
const visibleSetting = typeof visible === "boolean" ? visible : true;
|
|
265421
265521
|
const Visibility = useMemo$1(() => visibleSetting ? VisibilityIcon : VisibilityOffIcon, [visibleSetting]);
|
|
@@ -265431,19 +265531,19 @@ function ImageLayerController(props) {
|
|
|
265431
265531
|
}, [visible, setVisible]);
|
|
265432
265532
|
const handleOpacityChange = useCallback((e3, v) => setOpacity2(v), [setOpacity2]);
|
|
265433
265533
|
const handleOpenChange = useCallback(() => setOpen((prev2) => !prev2), []);
|
|
265434
|
-
const { classes: classes2 } = useStyles$
|
|
265534
|
+
const { classes: classes2 } = useStyles$9();
|
|
265435
265535
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
265436
265536
|
const { classes: controllerSectionClasses } = useControllerSectionStyles();
|
|
265437
265537
|
const isMultiChannel = photometricInterpretation !== "RGB";
|
|
265438
|
-
return jsx$1(Grid$1, { className: controllerSectionClasses.layerControllerGrid, children: jsxs(Paper, { elevation: 4, className: controllerSectionClasses.layerControllerRoot, children: [jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsx$1(Grid$1, { size: 1, children: jsx$1(Button, { className: menuClasses.imageLayerVisibleButton, onClick: handleVisibleChange, "aria-label": "Toggle layer visibility", children: jsx$1(Visibility, {}) }) }), jsx$1(Grid$1, { size: 1 }), jsx$1(Grid$1, { size: 6, children: jsx$1(Typography, { className: menuClasses.imageLayerName, children: label2 }) }), jsx$1(Grid$1, { size: 2, children: jsx$1(Slider, { value: opacity2, min: 0, max: 1, step: 1e-3, onChange: handleOpacityChange, className: menuClasses.imageLayerOpacitySlider, orientation: "horizontal", "aria-label": `Adjust opacity for layer ${label2}` }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(ImageLayerEllipsisMenu, { colormap, setColormap, photometricInterpretation, setPhotometricInterpretation, spatialTargetResolution, setSpatialTargetResolution, spatialLodFactor, setSpatialLodFactor, volumetricRenderingAlgorithm, setVolumetricRenderingAlgorithm, spatialLayerTransparentColor, setSpatialLayerTransparentColor, spatialRenderingMode, image: image2, channelScopes, tooltipsVisible, setTooltipsVisible, channelLabelsVisible, setChannelLabelsVisible, channelLabelsOrientation, setChannelLabelsOrientation, channelLabelSize, setChannelLabelSize }) }), jsxs(Grid$1, { size: 1, container: true, direction: "row", children: [jsx$1(ImageIcon, { className: classes2.layerTypeImageIcon }), isMultiChannel ? jsx$1(Button, { onClick: handleOpenChange, className: classes2.channelExpansionButton, "aria-label": "Expand or collapse channel controls", children: open2 ? jsx$1(ExpandLess, {}) : jsx$1(ExpandMoreIcon, {}) }) : null] })] }), isMultiChannel && open2 ? jsxs(Grid$1, { container: true, direction: "column", justifyContent: "space-between", className: classes2.imageChannelControllerGrid, children: [channelScopes.map((cScope) => {
|
|
265538
|
+
return jsx$1(Grid$1, { className: controllerSectionClasses.layerControllerGrid, children: jsxs(Paper, { elevation: 4, className: controllerSectionClasses.layerControllerRoot, children: [jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsx$1(Grid$1, { size: 1, children: jsx$1(Button, { className: menuClasses.imageLayerVisibleButton, onClick: handleVisibleChange, "aria-label": "Toggle layer visibility", children: jsx$1(Visibility, {}) }) }), jsx$1(Grid$1, { size: 1 }), jsx$1(Grid$1, { size: 6, children: jsx$1(Typography, { className: menuClasses.imageLayerName, children: label2 }) }), jsx$1(Grid$1, { size: 2, children: jsx$1(Slider, { value: opacity2, min: 0, max: 1, step: 1e-3, onChange: handleOpacityChange, className: menuClasses.imageLayerOpacitySlider, orientation: "horizontal", "aria-label": `Adjust opacity for layer ${label2}` }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(ImageLayerEllipsisMenu, { colormap, setColormap, photometricInterpretation, setPhotometricInterpretation, spatialTargetResolution, setSpatialTargetResolution, spatialLodFactor, setSpatialLodFactor, volumetricRenderingAlgorithm, setVolumetricRenderingAlgorithm, spatialLayerTransparentColor, setSpatialLayerTransparentColor, spatialRenderingMode, image: image2, channelScopes, tooltipsVisible, setTooltipsVisible, channelLabelsVisible, setChannelLabelsVisible, channelLabelsOrientation, setChannelLabelsOrientation, channelLabelSize, setChannelLabelSize, channelsSortOrder, setChannelsSortOrder }) }), jsxs(Grid$1, { size: 1, container: true, direction: "row", children: [jsx$1(ImageIcon, { className: classes2.layerTypeImageIcon }), isMultiChannel ? jsx$1(Button, { onClick: handleOpenChange, className: classes2.channelExpansionButton, "aria-label": "Expand or collapse channel controls", children: open2 ? jsx$1(ExpandLess, {}) : jsx$1(ExpandMoreIcon, {}) }) : null] })] }), isMultiChannel && open2 ? jsxs(Grid$1, { container: true, direction: "column", justifyContent: "space-between", className: classes2.imageChannelControllerGrid, children: [channelScopes.map((cScope) => {
|
|
265439
265539
|
const { spatialTargetC, spatialChannelVisible, spatialChannelOpacity, spatialChannelColor, spatialChannelWindow, spatialMaxResolution } = channelCoordination[cScope];
|
|
265440
265540
|
const { setSpatialTargetC, setSpatialChannelVisible, setSpatialChannelOpacity, setSpatialChannelColor, setSpatialChannelWindow, setSpatialMaxResolution } = setChannelCoordination[cScope];
|
|
265441
265541
|
const channelIndex = image2?.getChannelIndex(spatialTargetC);
|
|
265442
265542
|
const numResolutions = image2?.getNumResolutions();
|
|
265443
|
-
return jsx$1(ImageChannelController, { theme, coordinationScopesRaw, layerScope, channelScope: cScope, targetT, targetZ, targetC: channelIndex, setTargetC: setSpatialTargetC, visible: spatialChannelVisible, setVisible: setSpatialChannelVisible, opacity: spatialChannelOpacity, setOpacity: setSpatialChannelOpacity, color: spatialChannelColor, setColor: setSpatialChannelColor, window: spatialChannelWindow, setWindow: setSpatialChannelWindow, colormapOn: colormap !== null, featureIndex, image: image2, spatialRenderingMode, numResolutions, spatialMaxResolution, setSpatialMaxResolution }, cScope);
|
|
265543
|
+
return jsx$1(ImageChannelController, { theme, coordinationScopesRaw, layerScope, channelScope: cScope, targetT, targetZ, targetC: channelIndex, setTargetC: setSpatialTargetC, visible: spatialChannelVisible, setVisible: setSpatialChannelVisible, opacity: spatialChannelOpacity, setOpacity: setSpatialChannelOpacity, color: spatialChannelColor, setColor: setSpatialChannelColor, window: spatialChannelWindow, setWindow: setSpatialChannelWindow, colormapOn: colormap !== null, featureIndex, image: image2, channelsSortOrder, spatialRenderingMode, numResolutions, spatialMaxResolution, setSpatialMaxResolution }, cScope);
|
|
265444
265544
|
}), jsx$1(Button, { disabled: channelScopes.length === MAX_CHANNELS$1 || channelScopes.length === imageNumChannels, onClick: handleChannelAdd, fullWidth: true, variant: "outlined", className: classes2.imageLayerButton, startIcon: jsx$1(AddIcon, {}), size: "small", "aria-label": "Add a channel to this layer", children: "Add Channel" })] }) : null, is3dMode && image2 ? jsxs(Grid$1, { container: true, direction: "column", justifyContent: "space-between", className: classes2.imageChannelControllerGrid, children: [jsx$1(Typography, { className: classes2.clippingPanesLabel, children: "Clipping planes:" }), jsx$1(Grid$1, { size: 12, className: classes2.clippingSliders, children: jsx$1(ClippingSliders, { image: image2, spatialSliceX, spatialSliceY, spatialSliceZ, setSpatialSliceX, setSpatialSliceY, setSpatialSliceZ }) }), jsx$1(LoadingStatusIndicator, { loadingProgress: volumeLoadingProgress, onStopLoading: onStopVolumeLoading, onRestartLoading: onRestartVolumeLoading, stillRef: volumeStillRef, spatialRenderingMode })] }) : null] }) });
|
|
265445
265545
|
}
|
|
265446
|
-
const useStyles$
|
|
265546
|
+
const useStyles$8 = makeStyles()((theme) => ({
|
|
265447
265547
|
dimensionsIcon: {
|
|
265448
265548
|
height: "40px",
|
|
265449
265549
|
width: "40px",
|
|
@@ -265467,7 +265567,7 @@ const useStyles$7 = makeStyles()((theme) => ({
|
|
|
265467
265567
|
function GlobalDimensionSlider(props) {
|
|
265468
265568
|
const { label: label2, targetValue, setTargetValue, min: min2 = 0, max: max2 = 0, spatialRenderingMode = null, setSpatialRenderingMode = null } = props;
|
|
265469
265569
|
const { classes: lcClasses } = useControllerSectionStyles();
|
|
265470
|
-
const { classes: classes2 } = useStyles$
|
|
265570
|
+
const { classes: classes2 } = useStyles$8();
|
|
265471
265571
|
const isForZ = spatialRenderingMode !== null;
|
|
265472
265572
|
const is3dMode = spatialRenderingMode === "3D";
|
|
265473
265573
|
function handleRenderingModeChange(event2) {
|
|
@@ -265478,20 +265578,115 @@ function GlobalDimensionSlider(props) {
|
|
|
265478
265578
|
}
|
|
265479
265579
|
return jsx$1(Grid$1, { className: lcClasses.layerControllerGrid, children: jsx$1(Paper, { elevation: 4, className: lcClasses.layerControllerRoot, children: jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsx$1(Grid$1, { size: 1, children: jsx$1(SvgDimensions, { className: classes2.dimensionsIcon }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(Typography, { className: classes2.dimensionLabel, children: label2 }) }), jsx$1(Grid$1, { size: 8, children: !is3dMode ? jsx$1(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` }) : null }), jsx$1(Grid$1, { size: 2, children: isForZ ? jsx$1(FormGroup, { row: true, className: classes2.switchFormGroup, children: jsx$1(FormControlLabel$1, { control: jsx$1(Switch, { color: "primary", checked: spatialRenderingMode === "3D", onChange: handleRenderingModeChange, name: "is3dMode" }), label: "3D" }) }) : null })] }) }) });
|
|
265480
265580
|
}
|
|
265581
|
+
const useStyles$7 = makeStyles()(() => ({
|
|
265582
|
+
layerTypeCentroidSegmentationIcon: {
|
|
265583
|
+
height: "100%",
|
|
265584
|
+
marginLeft: "1px",
|
|
265585
|
+
fill: "currentColor",
|
|
265586
|
+
fontSize: "24px",
|
|
265587
|
+
width: "50%",
|
|
265588
|
+
maxWidth: "24px"
|
|
265589
|
+
},
|
|
265590
|
+
divider: {
|
|
265591
|
+
width: "1px",
|
|
265592
|
+
height: "20px",
|
|
265593
|
+
background: "currentColor",
|
|
265594
|
+
flexShrink: 0,
|
|
265595
|
+
margin: "0 10px"
|
|
265596
|
+
},
|
|
265597
|
+
inlineLabel: {
|
|
265598
|
+
margin: "0px !important",
|
|
265599
|
+
lineHeight: 1,
|
|
265600
|
+
alignSelf: "center"
|
|
265601
|
+
},
|
|
265602
|
+
iconCell: {
|
|
265603
|
+
display: "flex",
|
|
265604
|
+
alignItems: "center",
|
|
265605
|
+
justifyContent: "center"
|
|
265606
|
+
}
|
|
265607
|
+
}));
|
|
265608
|
+
function CombinedEllipsisMenu(props) {
|
|
265609
|
+
const { obsType, featureType, featureValueType, filled, setFilled, strokeWidth, setStrokeWidth, obsColorEncoding, setObsColorEncoding, featureValueColormap, setFeatureValueColormap, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible, setPointObsColorEncoding, setPointFeatureValueColormap, setPointFeatureValueColormapRange, onColorEncodingChange } = props;
|
|
265610
|
+
const [open2, setOpen] = useState(false);
|
|
265611
|
+
const { classes: selectClasses2 } = useSelectStyles();
|
|
265612
|
+
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
265613
|
+
const filledId = $bdb11010cef70236$export$f680877a34711e37();
|
|
265614
|
+
const strokeWidthId = $bdb11010cef70236$export$f680877a34711e37();
|
|
265615
|
+
const colorEncodingId = $bdb11010cef70236$export$f680877a34711e37();
|
|
265616
|
+
const colormapId = $bdb11010cef70236$export$f680877a34711e37();
|
|
265617
|
+
const colormapRangeId = $bdb11010cef70236$export$f680877a34711e37();
|
|
265618
|
+
const tooltipsId = $bdb11010cef70236$export$f680877a34711e37();
|
|
265619
|
+
const crosshairsId = $bdb11010cef70236$export$f680877a34711e37();
|
|
265620
|
+
const legendId = $bdb11010cef70236$export$f680877a34711e37();
|
|
265621
|
+
return jsxs(PopperMenu, { open: open2, setOpen, buttonIcon: jsx$1(MoreVertIcon, {}), buttonClassName: menuClasses.imageLayerMenuButton, containerClassName: menuClasses.imageLayerPopperContainer, withPaper: true, getAriaLabel: () => "Open combined centroid and segmentation layer options menu", children: [jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: filledId, children: "Filled: " }), jsx$1(Checkbox$1, { color: "primary", className: menuClasses.menuItemCheckbox, checked: filled, onChange: (e3, v) => setFilled(v), slotProps: { input: { id: filledId } } })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: strokeWidthId, children: "Stroke width:" }), jsx$1(Slider, { disabled: filled, value: strokeWidth, min: 0.01, max: 5, step: 0.01, onChange: (e3, v) => setStrokeWidth(v), className: menuClasses.menuItemSlider, orientation: "horizontal", id: strokeWidthId, getAriaLabel: () => "Stroke width" })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: colorEncodingId, children: "Color encoding: " }), jsxs(NativeSelect, { onChange: onColorEncodingChange, value: obsColorEncoding, inputProps: { id: colorEncodingId }, classes: { root: selectClasses2.selectRoot }, children: [jsx$1("option", { value: "spatialChannelColor", children: "Static Color" }), jsx$1("option", { value: "geneSelection", children: "Feature Value" }), jsx$1("option", { value: "cellSetSelection", children: "Set Selection" })] })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: colormapId, children: "Colormap: " }), jsx$1(NativeSelect, { onChange: (e3) => {
|
|
265622
|
+
setFeatureValueColormap(e3.target.value);
|
|
265623
|
+
setPointFeatureValueColormap?.(e3.target.value);
|
|
265624
|
+
}, value: featureValueColormap, inputProps: { id: colormapId }, classes: { root: selectClasses2.selectRoot }, children: GLSL_COLORMAPS.map((cmap) => jsx$1("option", { value: cmap, children: cmap }, cmap)) })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: colormapRangeId, children: "Colormap range: " }), jsx$1(Slider, { disabled: obsColorEncoding !== "geneSelection", value: featureValueColormapRange, min: 0, max: 1, step: 0.01, onChange: (e3, v) => {
|
|
265625
|
+
setFeatureValueColormapRange(v);
|
|
265626
|
+
setPointFeatureValueColormapRange?.(v);
|
|
265627
|
+
}, className: menuClasses.menuItemSlider, orientation: "horizontal", id: colormapRangeId, getAriaLabel: (i2) => i2 === 0 ? "Low colormap range" : "High colormap range" })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: tooltipsId, children: "Tooltips visible: " }), jsx$1(Checkbox$1, { color: "primary", className: menuClasses.menuItemCheckbox, checked: tooltipsVisible, onChange: (e3, v) => setTooltipsVisible(v), slotProps: { input: { id: tooltipsId } } })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: crosshairsId, children: "Crosshairs visible: " }), jsx$1(Checkbox$1, { color: "primary", className: menuClasses.menuItemCheckbox, checked: tooltipCrosshairsVisible, onChange: (e3, v) => setTooltipCrosshairsVisible(v), slotProps: { input: { id: crosshairsId } } })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: legendId, children: "Legend visible: " }), jsx$1(Checkbox$1, { color: "primary", className: menuClasses.menuItemCheckbox, checked: legendVisible, onChange: (e3, v) => setLegendVisible(v), slotProps: { input: { id: legendId } } })] })] });
|
|
265628
|
+
}
|
|
265629
|
+
function SegmentationCentroidsController(props) {
|
|
265630
|
+
const { theme, segScope, segLayerCoordination, segChannelScopesByLayer, segChannelCoordination, pointScope, pointLayerCoordination } = props;
|
|
265631
|
+
const { classes: classes2 } = useStyles$7();
|
|
265632
|
+
const { classes: lcClasses } = useControllerSectionStyles();
|
|
265633
|
+
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
265634
|
+
const channelScopes = segChannelScopesByLayer?.[segScope] ?? [];
|
|
265635
|
+
const primaryChanScope = channelScopes[0];
|
|
265636
|
+
const chanValues = segChannelCoordination[0]?.[segScope]?.[primaryChanScope] ?? {};
|
|
265637
|
+
const chanSetters = segChannelCoordination[1]?.[segScope]?.[primaryChanScope] ?? {};
|
|
265638
|
+
const { obsType, featureType, featureValueType, spatialChannelVisible: segVisible, spatialChannelOpacity: segOpacity, spatialChannelColor: segColor, spatialSegmentationFilled: filled, spatialSegmentationStrokeWidth: strokeWidth, obsColorEncoding, featureSelection, featureValueColormap, featureValueColormapRange, tooltipsVisible, tooltipCrosshairsVisible, legendVisible } = chanValues;
|
|
265639
|
+
const { setSpatialChannelVisible: setSegVisible, setSpatialChannelOpacity: setSegOpacity, setSpatialChannelColor: setSegColor, setSpatialSegmentationFilled: setFilled, setSpatialSegmentationStrokeWidth: setStrokeWidth, setObsColorEncoding, setFeatureValueColormap, setFeatureValueColormapRange, setTooltipsVisible, setTooltipCrosshairsVisible, setLegendVisible } = chanSetters;
|
|
265640
|
+
const pointValues = pointLayerCoordination[0]?.[pointScope] ?? {};
|
|
265641
|
+
const pointSetters = pointLayerCoordination[1]?.[pointScope] ?? {};
|
|
265642
|
+
const { spatialLayerVisible: pointVisible, spatialLayerOpacity: pointOpacity, spatialLayerColor: pointColor, obsColorEncoding: pointObsColorEncoding, featureValueColormap: pointFeatureValueColormap } = pointValues;
|
|
265643
|
+
const { setSpatialLayerVisible: setPointVisible, setSpatialLayerOpacity: setPointOpacity, setSpatialLayerColor: setPointColor, setObsColorEncoding: setPointObsColorEncoding, setFeatureValueColormap: setPointFeatureValueColormap, setFeatureValueColormapRange: setPointFeatureValueColormapRange } = pointSetters;
|
|
265644
|
+
const sharedOpacity = segOpacity ?? 1;
|
|
265645
|
+
const handleOpacityChange = useCallback((e3, v) => {
|
|
265646
|
+
setSegOpacity?.(v);
|
|
265647
|
+
setPointOpacity?.(v);
|
|
265648
|
+
}, [setSegOpacity, setPointOpacity]);
|
|
265649
|
+
const handleSegVisibleChange = useCallback(() => {
|
|
265650
|
+
setSegVisible?.(typeof segVisible === "boolean" ? !segVisible : false);
|
|
265651
|
+
}, [segVisible, setSegVisible]);
|
|
265652
|
+
const handlePointVisibleChange = useCallback(() => {
|
|
265653
|
+
setPointVisible?.(typeof pointVisible === "boolean" ? !pointVisible : false);
|
|
265654
|
+
}, [pointVisible, setPointVisible]);
|
|
265655
|
+
const handleColorEncodingChange = useCallback((e3) => {
|
|
265656
|
+
const val = e3.target.value;
|
|
265657
|
+
setObsColorEncoding(val);
|
|
265658
|
+
if (val === "geneSelection") {
|
|
265659
|
+
setPointObsColorEncoding?.("geneSelection");
|
|
265660
|
+
} else if (val === "cellSetSelection") {
|
|
265661
|
+
setPointObsColorEncoding?.("cellSetSelection");
|
|
265662
|
+
} else {
|
|
265663
|
+
setPointObsColorEncoding?.("spatialChannelColor");
|
|
265664
|
+
}
|
|
265665
|
+
}, [setObsColorEncoding, setPointObsColorEncoding]);
|
|
265666
|
+
const segVisibleSetting = typeof segVisible === "boolean" ? segVisible : true;
|
|
265667
|
+
const pointVisibleSetting = typeof pointVisible === "boolean" ? pointVisible : true;
|
|
265668
|
+
const SegVisibility = segVisibleSetting ? VisibilityIcon : VisibilityOffIcon;
|
|
265669
|
+
const PointVisibility = pointVisibleSetting ? VisibilityIcon : VisibilityOffIcon;
|
|
265670
|
+
const isStaticColor = obsColorEncoding === "spatialChannelColor";
|
|
265671
|
+
const isColormap = obsColorEncoding === "geneSelection";
|
|
265672
|
+
const pointIsStaticColor = pointObsColorEncoding === "spatialChannelColor";
|
|
265673
|
+
const pointIsColormap = pointObsColorEncoding === "geneSelection";
|
|
265674
|
+
return jsx$1(Grid$1, { className: lcClasses.layerControllerGrid, children: jsx$1(Paper, { elevation: 4, className: lcClasses.layerControllerRoot, children: jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", alignItems: "center", children: [jsxs(Grid$1, { size: "grow", style: { display: "flex", alignItems: "center", minWidth: 0 }, children: [jsx$1(Button, { onClick: handleSegVisibleChange, className: menuClasses.imageLayerVisibleButton, getAriaLabel: () => "Toggle mesh visibility", children: jsx$1(SegVisibility, {}) }), jsx$1(ChannelColorPickerMenu, { theme, color: segColor, setColor: setSegColor, isStaticColor, isColormap, featureValueColormap, visible: segVisibleSetting }), jsx$1(Typography, { className: `${menuClasses.imageLayerName} ${classes2.inlineLabel}`, children: "Cell" }), jsx$1("div", { className: classes2.divider }), jsx$1(Button, { onClick: handlePointVisibleChange, className: menuClasses.imageLayerVisibleButton, getAriaLabel: () => "Toggle centroid visibility", children: jsx$1(PointVisibility, {}) }), jsx$1(ChannelColorPickerMenu, { theme, color: pointColor, setColor: setPointColor, isStaticColor: pointIsStaticColor, isColormap: pointIsColormap, featureValueColormap: pointFeatureValueColormap, visible: pointVisibleSetting }), jsx$1(Typography, { className: `${menuClasses.imageLayerName} ${classes2.inlineLabel}`, children: "Point" })] }), jsx$1(Grid$1, { size: 2, children: jsx$1(Slider, { value: sharedOpacity, min: 0, max: 1, step: 1e-3, onChange: handleOpacityChange, className: menuClasses.imageLayerOpacitySlider, orientation: "horizontal", getAriaLabel: () => "Adjust shared opacity" }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(CombinedEllipsisMenu, { obsType, featureType, featureValueType, filled, setFilled, strokeWidth, setStrokeWidth, obsColorEncoding, setObsColorEncoding, featureValueColormap, setFeatureValueColormap, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible, setPointObsColorEncoding, setPointFeatureValueColormap, setPointFeatureValueColormapRange, onColorEncodingChange: handleColorEncodingChange }) }), jsx$1(Grid$1, { size: 1, className: classes2.iconCell, children: jsx$1(SvgVector, { className: classes2.layerTypeCentroidSegmentationIcon }) })] }) }) });
|
|
265675
|
+
}
|
|
265481
265676
|
function LayerController(props) {
|
|
265482
|
-
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, layerPerFeatureForPoints } = props;
|
|
265677
|
+
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, layerPerFeatureForPoints, centroidSegmentationPairs = [], pairedSegScopes = /* @__PURE__ */ new Set(), pairedPointScopes = /* @__PURE__ */ new Set() } = props;
|
|
265483
265678
|
const anyLayerHasT = Object.values(images || {}).some((image2) => image2?.image?.instance.hasTStack());
|
|
265484
265679
|
const anyLayerHasZ = Object.values(images || {}).some((image2) => image2?.image?.instance.hasZStack());
|
|
265485
265680
|
const maxT = Object.values(images || {}).reduce((a2, h2) => Math.max(a2, h2?.image?.instance.getNumT()), 1) - 1;
|
|
265486
265681
|
const maxZ = Object.values(images || {}).reduce((a2, h2) => Math.max(a2, h2?.image?.instance.getNumZ()), 1) - 1;
|
|
265487
265682
|
const reversedImageLayerScopes = useMemo$1(() => [...imageLayerScopes || []].reverse(), [imageLayerScopes]);
|
|
265488
|
-
const reversedSegmentationLayerScopes = useMemo$1(() => [...segmentationLayerScopes || []].reverse(), [segmentationLayerScopes]);
|
|
265489
265683
|
const reversedSpotLayerScopes = useMemo$1(() => [...spotLayerScopes || []].reverse(), [spotLayerScopes]);
|
|
265490
|
-
const reversedPointLayerScopes = useMemo$1(() => [...pointLayerScopes || []].reverse(), [pointLayerScopes]);
|
|
265491
|
-
|
|
265684
|
+
const reversedPointLayerScopes = useMemo$1(() => [...pointLayerScopes || []].filter((scope) => !pairedPointScopes.has(scope)).reverse(), [pointLayerScopes, pairedPointScopes]);
|
|
265685
|
+
const reversedSegmentationLayerScopes = useMemo$1(() => [...segmentationLayerScopes || []].filter((scope) => !pairedSegScopes.has(scope)).reverse(), [segmentationLayerScopes, pairedSegScopes]);
|
|
265686
|
+
return jsxs("div", { children: [anyLayerHasZ ? jsx$1(GlobalDimensionSlider, { label: "Z", targetValue: targetZ, setTargetValue: setTargetZ, max: maxZ, spatialRenderingMode, setSpatialRenderingMode }) : null, anyLayerHasT ? jsx$1(GlobalDimensionSlider, { label: "T", targetValue: targetT, setTargetValue: setTargetT, max: maxT }) : null, centroidSegmentationPairs.map(({ pointScope, segScope }) => jsx$1(SegmentationCentroidsController, { theme, segScope, segLayerCoordination: segmentationLayerCoordination, segChannelScopesByLayer: segmentationChannelScopesByLayer, segChannelCoordination: segmentationChannelCoordination, pointScope, pointLayerCoordination }, `combined-${segScope}-${pointScope}`)), pointLayerScopes && reversedPointLayerScopes.map((layerScope) => jsx$1(PointLayerController, { theme, layerScope, layerCoordination: pointLayerCoordination[0][layerScope], setLayerCoordination: pointLayerCoordination[1][layerScope], pointMatrixIndicesData: pointMultiIndicesData?.[layerScope], tiledPointsLoadingProgress, layerPerFeatureForPoints }, layerScope)), spotLayerScopes && reversedSpotLayerScopes.map((layerScope) => jsx$1(SpotLayerController, { theme, layerScope, layerCoordination: spotLayerCoordination[0][layerScope], setLayerCoordination: spotLayerCoordination[1][layerScope] }, layerScope)), segmentationLayerScopes && reversedSegmentationLayerScopes.map((layerScope) => jsx$1(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) => jsx$1(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))] });
|
|
265492
265687
|
}
|
|
265493
265688
|
function LayerControllerSubscriber(props) {
|
|
265494
|
-
const { coordinationScopes: coordinationScopesRaw, coordinationScopesBy: coordinationScopesByRaw, closeButtonVisible, downloadButtonVisible, removeGridComponent, theme, title: title2 = "Spatial Layers", uuid: uuid2, layerPerFeatureForPoints = false, cameraPresets } = props;
|
|
265689
|
+
const { coordinationScopes: coordinationScopesRaw, coordinationScopesBy: coordinationScopesByRaw, closeButtonVisible, downloadButtonVisible, removeGridComponent, theme, title: title2 = "Spatial Layers", uuid: uuid2, layerPerFeatureForPoints = false, cameraPresets, helpText = ViewHelpMapping.LAYER_CONTROLLER_BETA } = props;
|
|
265495
265690
|
const loaders = useLoaders();
|
|
265496
265691
|
const mergeCoordination = useMergeCoordination();
|
|
265497
265692
|
const coordinationScopes = useCoordinationScopes(coordinationScopesRaw);
|
|
@@ -265579,7 +265774,8 @@ function LayerControllerSubscriber(props) {
|
|
|
265579
265774
|
CoordinationType$1.TOOLTIPS_VISIBLE,
|
|
265580
265775
|
CoordinationType$1.SPATIAL_CHANNEL_LABELS_VISIBLE,
|
|
265581
265776
|
CoordinationType$1.SPATIAL_CHANNEL_LABELS_ORIENTATION,
|
|
265582
|
-
CoordinationType$1.SPATIAL_CHANNEL_LABEL_SIZE
|
|
265777
|
+
CoordinationType$1.SPATIAL_CHANNEL_LABEL_SIZE,
|
|
265778
|
+
CoordinationType$1.SPATIAL_CHANNELS_SORT_ORDER
|
|
265583
265779
|
], coordinationScopes, coordinationScopesBy, CoordinationType$1.IMAGE_LAYER);
|
|
265584
265780
|
const imageChannelCoordination = useComplexCoordinationSecondary([
|
|
265585
265781
|
CoordinationType$1.SPATIAL_TARGET_C,
|
|
@@ -265620,6 +265816,40 @@ function LayerControllerSubscriber(props) {
|
|
|
265620
265816
|
CoordinationType$1.TOOLTIP_CROSSHAIRS_VISIBLE,
|
|
265621
265817
|
CoordinationType$1.LEGEND_VISIBLE
|
|
265622
265818
|
], coordinationScopes, coordinationScopesBy, CoordinationType$1.POINT_LAYER);
|
|
265819
|
+
const centroidSegmentationPairs = React__default.useMemo(() => {
|
|
265820
|
+
const pairs = [];
|
|
265821
|
+
const pairedSegScopes = /* @__PURE__ */ new Set();
|
|
265822
|
+
const pairedPointScopes = /* @__PURE__ */ new Set();
|
|
265823
|
+
pointLayerScopes.forEach((pointScope) => {
|
|
265824
|
+
const pointCoord = pointLayerCoordination[0][pointScope];
|
|
265825
|
+
if (!pointCoord)
|
|
265826
|
+
return;
|
|
265827
|
+
const pointObsType = pointCoord[CoordinationType$1.OBS_TYPE];
|
|
265828
|
+
if (!pointObsType)
|
|
265829
|
+
return;
|
|
265830
|
+
const matchingSegScope = segmentationLayerScopes.find((segScope) => {
|
|
265831
|
+
if (pairedSegScopes.has(segScope))
|
|
265832
|
+
return false;
|
|
265833
|
+
const channelScopes = segmentationChannelScopesByLayer[segScope] || [];
|
|
265834
|
+
return channelScopes.some((chanScope) => {
|
|
265835
|
+
const chanCoord = segmentationChannelCoordination[0]?.[segScope]?.[chanScope];
|
|
265836
|
+
return chanCoord?.[CoordinationType$1.OBS_TYPE] === pointObsType;
|
|
265837
|
+
});
|
|
265838
|
+
});
|
|
265839
|
+
if (matchingSegScope) {
|
|
265840
|
+
pairs.push({ pointScope, segScope: matchingSegScope });
|
|
265841
|
+
pairedSegScopes.add(matchingSegScope);
|
|
265842
|
+
pairedPointScopes.add(pointScope);
|
|
265843
|
+
}
|
|
265844
|
+
});
|
|
265845
|
+
return { pairs, pairedSegScopes, pairedPointScopes };
|
|
265846
|
+
}, [
|
|
265847
|
+
pointLayerScopes,
|
|
265848
|
+
pointLayerCoordination,
|
|
265849
|
+
segmentationLayerScopes,
|
|
265850
|
+
segmentationChannelScopesByLayer,
|
|
265851
|
+
segmentationChannelCoordination
|
|
265852
|
+
]);
|
|
265623
265853
|
const [{ volumeLoadingProgress: volumeLoadingStatus, tiledPointsLoadingProgress }] = useAuxiliaryCoordination([
|
|
265624
265854
|
"spatialAcceleratedVolumeLoadingProgress",
|
|
265625
265855
|
"spatialTiledPointsLoadingProgress"
|
|
@@ -265647,7 +265877,7 @@ function LayerControllerSubscriber(props) {
|
|
|
265647
265877
|
imageDataStatus,
|
|
265648
265878
|
pointMultiIndicesDataStatus
|
|
265649
265879
|
]);
|
|
265650
|
-
return jsx$1(TitleInfo, { title: title2, isScroll: true, closeButtonVisible, downloadButtonVisible, removeGridComponent, theme, isReady, errors, children: jsx$1(LayerController, { theme, coordinationScopesRaw, segmentationLayerScopes, segmentationLayerCoordination, segmentationChannelScopesByLayer, segmentationChannelCoordination, images: imageData, imageLayerScopes, imageLayerCoordination, targetT, targetZ, setTargetT, setTargetZ, spatialRenderingMode, setSpatialRenderingMode, imageChannelScopesByLayer, imageChannelCoordination, spotLayerScopes, spotLayerCoordination, pointLayerScopes, pointLayerCoordination, pointMultiIndicesData, layerPerFeatureForPoints, volumeLoadingStatus, tiledPointsLoadingProgress }) });
|
|
265880
|
+
return jsx$1(TitleInfo, { title: title2, isScroll: true, closeButtonVisible, downloadButtonVisible, removeGridComponent, theme, isReady, errors, helpText, children: jsx$1(LayerController, { theme, coordinationScopesRaw, segmentationLayerScopes, segmentationLayerCoordination, segmentationChannelScopesByLayer, segmentationChannelCoordination, images: imageData, imageLayerScopes, imageLayerCoordination, targetT, targetZ, setTargetT, setTargetZ, spatialRenderingMode, setSpatialRenderingMode, imageChannelScopesByLayer, imageChannelCoordination, spotLayerScopes, spotLayerCoordination, pointLayerScopes, pointLayerCoordination, pointMultiIndicesData, layerPerFeatureForPoints, volumeLoadingStatus, tiledPointsLoadingProgress, centroidSegmentationPairs: centroidSegmentationPairs.pairs, pairedSegScopes: centroidSegmentationPairs.pairedSegScopes, pairedPointScopes: centroidSegmentationPairs.pairedPointScopes }) });
|
|
265651
265881
|
}
|
|
265652
265882
|
const isIterable$2 = (obj) => Symbol.iterator in obj;
|
|
265653
265883
|
const hasIterableEntries = (value2) => (
|
|
@@ -267562,7 +267792,7 @@ function HiglassGlobalStyles(props) {
|
|
|
267562
267792
|
}
|
|
267563
267793
|
register({ dataFetcher: ZarrMultivecDataFetcher_default, config: ZarrMultivecDataFetcher_default.config }, { pluginType: "dataFetcher" });
|
|
267564
267794
|
const LazyHiGlassComponent = React__default.lazy(async () => {
|
|
267565
|
-
const { HiGlassComponent } = await import("./higlass-
|
|
267795
|
+
const { HiGlassComponent } = await import("./higlass-4OKx7mdy.js");
|
|
267566
267796
|
return { default: HiGlassComponent };
|
|
267567
267797
|
});
|
|
267568
267798
|
const HG_SIZE = 800;
|
|
@@ -267900,6 +268130,12 @@ const useStyles$4 = makeStyles()(() => ({
|
|
|
267900
268130
|
neuroglancerWrapper: {
|
|
267901
268131
|
position: "relative",
|
|
267902
268132
|
height: "100%"
|
|
268133
|
+
},
|
|
268134
|
+
meshLoadingIndicator: {
|
|
268135
|
+
position: "absolute",
|
|
268136
|
+
bottom: 8,
|
|
268137
|
+
left: 8,
|
|
268138
|
+
zIndex: 50
|
|
267903
268139
|
}
|
|
267904
268140
|
}));
|
|
267905
268141
|
const globalNeuroglancerCss = `
|
|
@@ -269151,13 +269387,16 @@ const globalNeuroglancerStyles = {
|
|
|
269151
269387
|
},
|
|
269152
269388
|
"input.perspective-panel-show-slice-views": { pointerEvents: "all" },
|
|
269153
269389
|
".neuroglancer-rendered-data-panel": {
|
|
269154
|
-
cursor: "
|
|
269390
|
+
cursor: "grab",
|
|
269155
269391
|
position: "relative",
|
|
269156
269392
|
outline: "0",
|
|
269157
269393
|
touchAction: "none",
|
|
269158
269394
|
color: "#fff",
|
|
269159
269395
|
textAlign: "left"
|
|
269160
269396
|
},
|
|
269397
|
+
".neuroglancer-rendered-data-panel:active": {
|
|
269398
|
+
cursor: "grabbing"
|
|
269399
|
+
},
|
|
269161
269400
|
".neuroglancer-display-dimensions-widget": {
|
|
269162
269401
|
position: "absolute",
|
|
269163
269402
|
cursor: "default",
|
|
@@ -270510,7 +270749,7 @@ function NeuroglancerGlobalStyles(props) {
|
|
|
270510
270749
|
const { classes: classes2 } = props;
|
|
270511
270750
|
return jsxs(Fragment, { children: [jsx$1(GlobalStyles$3, { styles: globalNeuroglancerCss }), jsx$1(ScopedGlobalStyles, { styles: globalNeuroglancerStyles, parentClassName: classes2.neuroglancerWrapper })] });
|
|
270512
270751
|
}
|
|
270513
|
-
const LazyReactNeuroglancer = React__default.lazy(() => import("./ReactNeuroglancer-
|
|
270752
|
+
const LazyReactNeuroglancer = React__default.lazy(() => import("./ReactNeuroglancer-DSiLDSuM.js"));
|
|
270514
270753
|
function createWorker() {
|
|
270515
270754
|
const worker = new WorkerFactory$1();
|
|
270516
270755
|
worker.AsyncComputationWorker = WorkerFactory;
|
|
@@ -270555,12 +270794,31 @@ class NeuroglancerComp extends PureComponent {
|
|
|
270555
270794
|
}
|
|
270556
270795
|
};
|
|
270557
270796
|
remapWheelToZoom(viewer.inputEventBindings.perspectiveView);
|
|
270797
|
+
const { getMeshIdToCellId, onViewerReady, cellsUrl } = this.props;
|
|
270558
270798
|
this.prevHoverHandler = () => {
|
|
270559
|
-
|
|
270560
|
-
|
|
270561
|
-
|
|
270799
|
+
const ms = viewer.mouseState;
|
|
270800
|
+
if (ms.pickedAnnotationId != null) {
|
|
270801
|
+
const byIdKey = String(ms.pickedAnnotationId);
|
|
270802
|
+
fetch(`${cellsUrl}/by_id/${byIdKey}`).then((r3) => r3.arrayBuffer()).then((buf) => {
|
|
270803
|
+
const dv = new DataView(buf);
|
|
270804
|
+
const actualMeshId = String(dv.getInt32(12, true));
|
|
270805
|
+
const cellId = getMeshIdToCellId?.(actualMeshId) ?? actualMeshId;
|
|
270806
|
+
this.latestOnSelectHoveredCoords?.(cellId);
|
|
270807
|
+
});
|
|
270808
|
+
return;
|
|
270809
|
+
}
|
|
270810
|
+
if (ms.pickedValue !== void 0 && ms.pickedValue !== null) {
|
|
270811
|
+
const meshId = String(ms.pickedValue?.low);
|
|
270812
|
+
const cellId = getMeshIdToCellId?.(meshId) ?? meshId;
|
|
270813
|
+
this.latestOnSelectHoveredCoords?.(cellId);
|
|
270814
|
+
return;
|
|
270562
270815
|
}
|
|
270816
|
+
this.latestOnSelectHoveredCoords?.(null);
|
|
270563
270817
|
};
|
|
270818
|
+
onViewerReady?.(() => {
|
|
270819
|
+
const panel = [...viewer.display.panels][0];
|
|
270820
|
+
return panel?.projectionParameters?.value_?.viewProjectionMat;
|
|
270821
|
+
});
|
|
270564
270822
|
viewer.mouseState.changed.add(this.prevHoverHandler);
|
|
270565
270823
|
} else {
|
|
270566
270824
|
if (this.prevMouseStateChanged && this.prevHoverHandler) {
|
|
@@ -270581,8 +270839,8 @@ class NeuroglancerComp extends PureComponent {
|
|
|
270581
270839
|
}
|
|
270582
270840
|
}
|
|
270583
270841
|
render() {
|
|
270584
|
-
const { classes: classes2, viewerState, cellColorMapping, onLayerLoadingChange } = this.props;
|
|
270585
|
-
return jsxs(Fragment, { children: [jsx$1(NeuroglancerGlobalStyles, { classes: classes2 }), jsx$1("div", { className: classes2.neuroglancerWrapper, children: jsx$1(Suspense, { fallback: jsx$1("div", { children: "Loading..." }), children: jsx$1(LazyReactNeuroglancer, { brainMapsClientId: "NOT_A_VALID_ID", viewerState, onViewerStateChanged: this.onViewerStateChanged, onLayerLoadingChange, bundleRoot: this.bundleRoot, cellColorMapping, ref: this.onRef }) }) })] });
|
|
270842
|
+
const { classes: classes2, viewerState, cellColorMapping, onLayerLoadingChange, onAnnotationSourceReady, onViewerReady, meshOpacity } = this.props;
|
|
270843
|
+
return jsxs(Fragment, { children: [jsx$1(NeuroglancerGlobalStyles, { classes: classes2 }), jsx$1("div", { className: classes2.neuroglancerWrapper, children: jsx$1(Suspense, { fallback: jsx$1("div", { children: "Loading..." }), children: jsx$1(LazyReactNeuroglancer, { brainMapsClientId: "NOT_A_VALID_ID", viewerState, onViewerStateChanged: this.onViewerStateChanged, onLayerLoadingChange, bundleRoot: this.bundleRoot, cellColorMapping, ref: this.onRef, onAnnotationSourceReady, onViewerReady, meshOpacity }) }) })] });
|
|
270586
270844
|
}
|
|
270587
270845
|
}
|
|
270588
270846
|
function useMemoCustomComparison(factory2, dependencies2, customIsEqual) {
|
|
@@ -270597,17 +270855,22 @@ function useMemoCustomComparison(factory2, dependencies2, customIsEqual) {
|
|
|
270597
270855
|
}
|
|
270598
270856
|
const shallowDiff = (prevDeps, nextDeps, depName) => prevDeps[depName] !== nextDeps[depName];
|
|
270599
270857
|
const shallowDiffByLayer = (prevDeps, nextDeps, depName, scopeName) => prevDeps?.[depName]?.[scopeName] !== nextDeps?.[depName]?.[scopeName];
|
|
270858
|
+
const shallowDiffByChannel = (prevDeps, nextDeps, depName, firstName, secondName) => prevDeps?.[depName]?.[firstName]?.[secondName] !== nextDeps?.[depName]?.[firstName]?.[secondName];
|
|
270600
270859
|
const shallowDiffByChannelWithKeys = (prevDeps, nextDeps, depName, firstName, secondName, keys2) => keys2.some((k) => prevDeps?.[depName]?.[firstName]?.[secondName]?.[k] !== nextDeps?.[depName]?.[firstName]?.[secondName]?.[k]);
|
|
270601
270860
|
const shallowDiffByLayerCoordinationWithKeys = (prevDeps, nextDeps, depName, layerScope, keys2) => keys2.some((k) => prevDeps?.[depName]?.[0]?.[layerScope]?.[k] !== nextDeps?.[depName]?.[0]?.[layerScope]?.[k]);
|
|
270602
270861
|
const shallowDiffByChannelCoordinationWithKeys = (prevDeps, nextDeps, depName, layerScope, channelScope, keys2) => keys2.some((k) => prevDeps?.[depName]?.[0]?.[layerScope]?.[channelScope]?.[k] !== nextDeps?.[depName]?.[0]?.[layerScope]?.[channelScope]?.[k]);
|
|
270603
270862
|
function customIsEqualForCellColors(prevDeps, nextDeps) {
|
|
270604
270863
|
let forceUpdate = false;
|
|
270605
270864
|
const curriedShallowDiff = (depName) => shallowDiff(prevDeps, nextDeps, depName);
|
|
270865
|
+
const curriedShallowDiffByChannel = (depName, firstName, secondName) => shallowDiffByChannel(prevDeps, nextDeps, depName, firstName, secondName);
|
|
270606
270866
|
const curriedShallowDiffByChannelWithKeys = (depName, firstName, secondName, keys2) => shallowDiffByChannelWithKeys(prevDeps, nextDeps, depName, firstName, secondName, keys2);
|
|
270607
270867
|
const curriedShallowDiffByChannelCoordinationWithKeys = (depName, layerScope, channelScope, keys2) => shallowDiffByChannelCoordinationWithKeys(prevDeps, nextDeps, depName, layerScope, channelScope, keys2);
|
|
270608
270868
|
if (curriedShallowDiff("theme")) {
|
|
270609
270869
|
forceUpdate = true;
|
|
270610
270870
|
}
|
|
270871
|
+
if (curriedShallowDiff("csvLoaded")) {
|
|
270872
|
+
forceUpdate = true;
|
|
270873
|
+
}
|
|
270611
270874
|
if (["segmentationLayerScopes", "segmentationChannelScopesByLayer"].some(curriedShallowDiff)) {
|
|
270612
270875
|
forceUpdate = true;
|
|
270613
270876
|
} else {
|
|
@@ -270622,8 +270885,11 @@ function customIsEqualForCellColors(prevDeps, nextDeps) {
|
|
|
270622
270885
|
"obsSetSelection",
|
|
270623
270886
|
"additionalObsSets",
|
|
270624
270887
|
"spatialChannelColor",
|
|
270625
|
-
"spatialChannelOpacity"
|
|
270626
|
-
|
|
270888
|
+
"spatialChannelOpacity",
|
|
270889
|
+
"featureValueColormap",
|
|
270890
|
+
"featureValueColormapRange",
|
|
270891
|
+
"featureSelection"
|
|
270892
|
+
]) || curriedShallowDiffByChannel("segmentationMultiIndicesData", layerScope, channelScope) || curriedShallowDiffByChannel("segmentationMultiExpressionNormData", layerScope, channelScope)) {
|
|
270627
270893
|
forceUpdate = true;
|
|
270628
270894
|
}
|
|
270629
270895
|
});
|
|
@@ -270669,7 +270935,13 @@ function customIsEqualForInitialViewerState(prevDeps, nextDeps) {
|
|
|
270669
270935
|
"featureSelection",
|
|
270670
270936
|
"featureFilterMode",
|
|
270671
270937
|
"featureColor",
|
|
270672
|
-
"spatialPointStrokeWidth"
|
|
270938
|
+
"spatialPointStrokeWidth",
|
|
270939
|
+
"featureValueColormap",
|
|
270940
|
+
"featureValueColormapRange",
|
|
270941
|
+
"featureSelection",
|
|
270942
|
+
"obsSetColor",
|
|
270943
|
+
"obsSetSelection",
|
|
270944
|
+
"additionalObsSets"
|
|
270673
270945
|
]) || Math.abs(prevDeps?.pointLayerCoordination?.[0]?.[layerScope]?.spatialLayerOpacity - nextDeps?.pointLayerCoordination?.[0]?.[layerScope]?.spatialLayerOpacity) >= 0.05) {
|
|
270674
270946
|
forceUpdate = true;
|
|
270675
270947
|
}
|
|
@@ -270723,6 +270995,35 @@ function getSpatialLayerColorWithSelectionShader(staticColor, opacity2, featureI
|
|
|
270723
270995
|
}
|
|
270724
270996
|
`;
|
|
270725
270997
|
}
|
|
270998
|
+
function getObsSetSelectionFilteredShader(phenotypeColors, selectedIndices, opacity2, borderWidth = 0) {
|
|
270999
|
+
const numColors = phenotypeColors.length;
|
|
271000
|
+
const numSelected = selectedIndices.length;
|
|
271001
|
+
const normColors = phenotypeColors.map((c2) => normalizeColor(c2));
|
|
271002
|
+
const colorsDecl = `vec3 phenotypeColors[${numColors}] = vec3[${numColors}](${normColors.map((c2) => toVec3(c2)).join(", ")});`;
|
|
271003
|
+
const selectedDecl = `int selectedIndices[${numSelected}] = int[${numSelected}](${selectedIndices.join(", ")});`;
|
|
271004
|
+
return `
|
|
271005
|
+
void main() {
|
|
271006
|
+
int phenotype = prop_phenotype();
|
|
271007
|
+
${colorsDecl}
|
|
271008
|
+
${selectedDecl}
|
|
271009
|
+
bool isSelected = false;
|
|
271010
|
+
for (int i = 0; i < ${numSelected}; ++i) {
|
|
271011
|
+
if (phenotype == selectedIndices[i]) {
|
|
271012
|
+
isSelected = true;
|
|
271013
|
+
}
|
|
271014
|
+
}
|
|
271015
|
+
if (!isSelected) {
|
|
271016
|
+
discard;
|
|
271017
|
+
}
|
|
271018
|
+
vec3 color = vec3(0.5, 0.5, 0.5);
|
|
271019
|
+
if (phenotype >= 0 && phenotype < ${numColors}) {
|
|
271020
|
+
color = phenotypeColors[phenotype];
|
|
271021
|
+
}
|
|
271022
|
+
setColor(vec4(color, ${opacity2.toFixed(4)}));
|
|
271023
|
+
${borderWidthGlsl(borderWidth)}
|
|
271024
|
+
}
|
|
271025
|
+
`;
|
|
271026
|
+
}
|
|
270726
271027
|
function getSpatialLayerColorFilteredShader(staticColor, opacity2, featureIndices, featureIndexProp, borderWidth = 0) {
|
|
270727
271028
|
const normStatic = normalizeColor(staticColor);
|
|
270728
271029
|
const numFeatures = featureIndices.length;
|
|
@@ -270904,6 +271205,23 @@ function getRandomPerPointShader(opacity2, featureIndexProp, pointIndexProp, bor
|
|
|
270904
271205
|
}
|
|
270905
271206
|
`;
|
|
270906
271207
|
}
|
|
271208
|
+
function getQuantitativeColormapShader(quantitativeColorProp, opacity2, colormap = GLSL_COLORMAP_DEFAULT, colormapRange = [0, 1], borderWidth = 0, quantitativeColorMax = 1) {
|
|
271209
|
+
const [low, high] = colormapRange;
|
|
271210
|
+
const resolvedColormap = GLSL_COLORMAPS.includes(colormap) ? colormap : GLSL_COLORMAP_DEFAULT;
|
|
271211
|
+
return `
|
|
271212
|
+
#define COLORMAP_FUNC ${resolvedColormap}
|
|
271213
|
+
${colormaps$1}
|
|
271214
|
+
void main() {
|
|
271215
|
+
float rawVal = float(prop_${quantitativeColorProp}());
|
|
271216
|
+
float normalizedVal = rawVal / ${quantitativeColorMax.toFixed(4)};
|
|
271217
|
+
float t = (normalizedVal - ${low.toFixed(4)}) / max(${(high - low).toFixed(4)}, 0.0001);
|
|
271218
|
+
t = clamp(t, 0.0, 1.0);
|
|
271219
|
+
vec4 col = COLORMAP_FUNC(t);
|
|
271220
|
+
setColor(vec4(col.rgb, ${opacity2.toFixed(4)}));
|
|
271221
|
+
${borderWidthGlsl(borderWidth)}
|
|
271222
|
+
}
|
|
271223
|
+
`;
|
|
271224
|
+
}
|
|
270907
271225
|
function getRandomPerPointWithSelectionShader(featureIndices, defaultColor, opacity2, featureIndexProp, pointIndexProp, borderWidth = 0) {
|
|
270908
271226
|
const normDefault = normalizeColor(defaultColor);
|
|
270909
271227
|
const numFeatures = featureIndices.length;
|
|
@@ -270959,8 +271277,25 @@ function getRandomPerPointFilteredShader(featureIndices, opacity2, featureIndexP
|
|
|
270959
271277
|
}
|
|
270960
271278
|
`;
|
|
270961
271279
|
}
|
|
271280
|
+
function getObsSetSelectionShader(phenotypeColors, opacity2, borderWidth = 0) {
|
|
271281
|
+
const numColors = phenotypeColors.length;
|
|
271282
|
+
const normColors = phenotypeColors.map((c2) => normalizeColor(c2));
|
|
271283
|
+
const colorsDecl = `vec3 phenotypeColors[${numColors}] = vec3[${numColors}](${normColors.map((c2) => toVec3(c2)).join(", ")});`;
|
|
271284
|
+
return `
|
|
271285
|
+
void main() {
|
|
271286
|
+
int phenotype = prop_phenotype();
|
|
271287
|
+
${colorsDecl}
|
|
271288
|
+
vec3 color = ${toVec3(normalizeColor([128, 128, 128]))};
|
|
271289
|
+
if (phenotype >= 0 && phenotype < ${numColors}) {
|
|
271290
|
+
color = phenotypeColors[phenotype];
|
|
271291
|
+
}
|
|
271292
|
+
setColor(vec4(color, ${opacity2.toFixed(4)}));
|
|
271293
|
+
${borderWidthGlsl(borderWidth)}
|
|
271294
|
+
}
|
|
271295
|
+
`;
|
|
271296
|
+
}
|
|
270962
271297
|
function getPointsShader(layerCoordination) {
|
|
270963
|
-
const { theme, featureIndex, spatialLayerOpacity, obsColorEncoding, spatialLayerColor, featureSelection, featureFilterMode, featureColor, pointMarkerBorderWidth = 0, featureIndexProp, pointIndexProp } = layerCoordination;
|
|
271298
|
+
const { theme, featureIndex, spatialLayerOpacity, obsColorEncoding, spatialLayerColor, featureSelection, featureFilterMode, featureColor, pointMarkerBorderWidth = 0, featureIndexProp, pointIndexProp, quantitativeColorProp, featureValueColormap, featureValueColormapRange, obsSetColor, obsSetSelection, quantitativeColorMax, pointsAreSegmentationCentroids } = layerCoordination;
|
|
270964
271299
|
const defaultColor = getDefaultColor(theme);
|
|
270965
271300
|
const opacity2 = spatialLayerOpacity ?? 1;
|
|
270966
271301
|
const staticColor = Array.isArray(spatialLayerColor) && spatialLayerColor.length === 3 ? spatialLayerColor : defaultColor;
|
|
@@ -270984,7 +271319,7 @@ function getPointsShader(layerCoordination) {
|
|
|
270984
271319
|
}
|
|
270985
271320
|
return getSpatialLayerColorWithSelectionShader(staticColor, opacity2, featureIndices, defaultColor, featureIndexProp, pointMarkerBorderWidth);
|
|
270986
271321
|
}
|
|
270987
|
-
if (obsColorEncoding === "geneSelection") {
|
|
271322
|
+
if (obsColorEncoding === "geneSelection" && !pointsAreSegmentationCentroids) {
|
|
270988
271323
|
if (!featureIndexProp) {
|
|
270989
271324
|
throw new Error("In order to use gene-based color encoding for Neuroglancer Points, options.featureIndexProp must be specified for the obsPoints.ng-annotations fileType in the Vitessce configuration.");
|
|
270990
271325
|
}
|
|
@@ -271020,19 +271355,49 @@ function getPointsShader(layerCoordination) {
|
|
|
271020
271355
|
}
|
|
271021
271356
|
return getRandomPerPointWithSelectionShader(featureIndices, defaultColor, opacity2, featureIndexProp, pointIndexProp, pointMarkerBorderWidth);
|
|
271022
271357
|
}
|
|
271358
|
+
if (obsColorEncoding === "geneSelection" && pointsAreSegmentationCentroids) {
|
|
271359
|
+
if (!quantitativeColorProp) {
|
|
271360
|
+
console.warn("In order to use quantitative colormap encoding for Neuroglancer Points, options.quantitativeColorProp must be specified for the obsPoints.ng-annotations fileType in the Vitessce configuration. Falling back to static color.");
|
|
271361
|
+
return getSpatialLayerColorShader(staticColor, opacity2, pointMarkerBorderWidth);
|
|
271362
|
+
}
|
|
271363
|
+
return getQuantitativeColormapShader(quantitativeColorProp, opacity2, featureValueColormap, featureValueColormapRange, pointMarkerBorderWidth, quantitativeColorMax);
|
|
271364
|
+
}
|
|
271365
|
+
if (obsColorEncoding === "cellSetSelection") {
|
|
271366
|
+
if (!obsSetColor || !obsSetSelection) {
|
|
271367
|
+
return getSpatialLayerColorShader(staticColor, opacity2, pointMarkerBorderWidth);
|
|
271368
|
+
}
|
|
271369
|
+
const colorByName = {};
|
|
271370
|
+
obsSetColor?.forEach(({ path: path2, color: color2 }) => {
|
|
271371
|
+
if (path2?.length > 1) {
|
|
271372
|
+
colorByName[path2[path2.length - 1]] = color2;
|
|
271373
|
+
}
|
|
271374
|
+
});
|
|
271375
|
+
const uniqueNames = Object.keys(colorByName).sort();
|
|
271376
|
+
const phenotypeColors = uniqueNames.map((name2) => colorByName[name2] ?? defaultColor);
|
|
271377
|
+
if (isFiltered) {
|
|
271378
|
+
const selectedNames = new Set(obsSetSelection?.map((path2) => path2[path2.length - 1]) ?? []);
|
|
271379
|
+
const selectedIndices = uniqueNames.map((name2, idx) => selectedNames.has(name2) ? idx : -1).filter((idx) => idx >= 0);
|
|
271380
|
+
if (selectedIndices.length === 0) {
|
|
271381
|
+
return "void main() { discard; }";
|
|
271382
|
+
}
|
|
271383
|
+
return getObsSetSelectionFilteredShader(phenotypeColors, selectedIndices, opacity2, pointMarkerBorderWidth);
|
|
271384
|
+
}
|
|
271385
|
+
return getObsSetSelectionShader(phenotypeColors, opacity2, pointMarkerBorderWidth);
|
|
271386
|
+
}
|
|
271023
271387
|
return getSpatialLayerColorShader(staticColor, opacity2, pointMarkerBorderWidth);
|
|
271024
271388
|
}
|
|
271389
|
+
const DEFAULT_NG_DIMENSIONS = {
|
|
271390
|
+
x: [1, "nm"],
|
|
271391
|
+
y: [1, "nm"],
|
|
271392
|
+
z: [1, "nm"]
|
|
271393
|
+
};
|
|
271025
271394
|
const DEFAULT_NG_PROPS = {
|
|
271026
271395
|
layout: "3d",
|
|
271027
271396
|
position: [0, 0, 0],
|
|
271028
271397
|
projectionOrientation: [0, 0, 0, 1],
|
|
271029
271398
|
projectionScale: 1024,
|
|
271030
271399
|
crossSectionScale: 1,
|
|
271031
|
-
dimensions:
|
|
271032
|
-
x: [1, "nm"],
|
|
271033
|
-
y: [1, "nm"],
|
|
271034
|
-
z: [1, "nm"]
|
|
271035
|
-
},
|
|
271400
|
+
dimensions: DEFAULT_NG_DIMENSIONS,
|
|
271036
271401
|
layers: []
|
|
271037
271402
|
};
|
|
271038
271403
|
function toPrecomputedSource(url) {
|
|
@@ -271050,6 +271415,15 @@ function toNgLayerName(dataType, layerScope, channelScope = null) {
|
|
|
271050
271415
|
}
|
|
271051
271416
|
throw new Error(`Unsupported data type: ${dataType}`);
|
|
271052
271417
|
}
|
|
271418
|
+
function pointsHaveMatchingSegmentation({ pointObsType, segmentationLayerScopes, segmentationChannelScopesByLayer, segmentationChannelCoordination }) {
|
|
271419
|
+
return segmentationLayerScopes.some((segmentationLayerScope) => {
|
|
271420
|
+
const segmentationChannelScopes = segmentationChannelScopesByLayer?.[segmentationLayerScope] || [];
|
|
271421
|
+
return segmentationChannelScopes.some((segmentationChannelScope) => {
|
|
271422
|
+
const segmentationObsType = segmentationChannelCoordination?.[0]?.[segmentationLayerScope]?.[segmentationChannelScope]?.obsType;
|
|
271423
|
+
return segmentationObsType && pointObsType && segmentationObsType === pointObsType;
|
|
271424
|
+
});
|
|
271425
|
+
});
|
|
271426
|
+
}
|
|
271053
271427
|
function useNeuroglancerViewerState(theme, showAxisLines, segmentationLayerScopes, segmentationChannelScopesByLayer, segmentationLayerCoordination, segmentationChannelCoordination, obsSegmentationsUrls, obsSegmentationsData, pointLayerScopes, pointLayerCoordination, obsPointsUrls, obsPointsData, pointMultiIndicesData) {
|
|
271054
271428
|
const viewerState = useMemoCustomComparison(() => {
|
|
271055
271429
|
let result = cloneDeep$1(DEFAULT_NG_PROPS);
|
|
@@ -271072,6 +271446,9 @@ function useNeuroglancerViewerState(theme, showAxisLines, segmentationLayerScope
|
|
|
271072
271446
|
} : toPrecomputedSource(layerUrl);
|
|
271073
271447
|
result = {
|
|
271074
271448
|
...result,
|
|
271449
|
+
showAxisLines,
|
|
271450
|
+
showDefaultAnnotations: false,
|
|
271451
|
+
// this removes the yellow box around pointsLayer
|
|
271075
271452
|
layers: [
|
|
271076
271453
|
...result.layers,
|
|
271077
271454
|
{
|
|
@@ -271095,9 +271472,27 @@ function useNeuroglancerViewerState(theme, showAxisLines, segmentationLayerScope
|
|
|
271095
271472
|
const layerCoordination = pointLayerCoordination[0][layerScope];
|
|
271096
271473
|
const layerData = obsPointsData[layerScope];
|
|
271097
271474
|
const layerUrl = obsPointsUrls[layerScope]?.[0]?.url;
|
|
271475
|
+
const ngOptions = layerData?.neuroglancerOptions;
|
|
271476
|
+
if (ngOptions?.transform?.matrix && ngOptions?.transform?.outputDimensions) {
|
|
271477
|
+
result = {
|
|
271478
|
+
...result,
|
|
271479
|
+
dimensions: ngOptions.transform.outputDimensions ?? DEFAULT_NG_DIMENSIONS
|
|
271480
|
+
};
|
|
271481
|
+
}
|
|
271482
|
+
const pointsAreSegmentationCentroids = pointsHaveMatchingSegmentation({
|
|
271483
|
+
pointObsType: layerCoordination?.obsType,
|
|
271484
|
+
segmentationLayerScopes,
|
|
271485
|
+
segmentationChannelScopesByLayer,
|
|
271486
|
+
segmentationChannelCoordination
|
|
271487
|
+
});
|
|
271098
271488
|
const featureIndex = pointMultiIndicesData[layerScope]?.featureIndex;
|
|
271099
271489
|
if (layerUrl && layerData) {
|
|
271100
|
-
const { spatialLayerVisible, spatialLayerOpacity, obsColorEncoding, spatialLayerColor, featureSelection, featureFilterMode, featureColor, spatialPointStrokeWidth } = layerCoordination || {};
|
|
271490
|
+
const { spatialLayerVisible, spatialLayerOpacity, obsColorEncoding, spatialLayerColor, featureSelection, featureFilterMode, featureColor, spatialPointStrokeWidth, featureValueColormap, featureValueColormapRange } = layerCoordination || {};
|
|
271491
|
+
const quantitativeColorMax = layerData.neuroglancerOptions?.quantitativeColorMax;
|
|
271492
|
+
if (!quantitativeColorMax && obsColorEncoding === "geneSelection") {
|
|
271493
|
+
console.warn("quantitativeColorMax not specified in options — defaulting to 1.0 (no normalization)");
|
|
271494
|
+
}
|
|
271495
|
+
const quantitativeColorMaxSelected = quantitativeColorMax ?? 1;
|
|
271101
271496
|
const shader = getPointsShader({
|
|
271102
271497
|
theme,
|
|
271103
271498
|
featureIndex,
|
|
@@ -271107,9 +271502,18 @@ function useNeuroglancerViewerState(theme, showAxisLines, segmentationLayerScope
|
|
|
271107
271502
|
featureSelection,
|
|
271108
271503
|
featureFilterMode,
|
|
271109
271504
|
featureColor,
|
|
271505
|
+
featureValueColormap,
|
|
271506
|
+
featureValueColormapRange,
|
|
271110
271507
|
featureIndexProp: layerData.neuroglancerOptions?.featureIndexProp,
|
|
271111
271508
|
pointIndexProp: layerData.neuroglancerOptions?.pointIndexProp,
|
|
271112
|
-
|
|
271509
|
+
quantitativeColorProp: layerData.neuroglancerOptions?.quantitativeColorProp,
|
|
271510
|
+
pointMarkerBorderWidth: spatialPointStrokeWidth ?? 0,
|
|
271511
|
+
obsSets: layerCoordination.obsSets,
|
|
271512
|
+
obsSetColor: layerCoordination.obsSetColor,
|
|
271513
|
+
obsSetSelection: layerCoordination.obsSetSelection,
|
|
271514
|
+
additionalObsSets: layerCoordination.additionalObsSets,
|
|
271515
|
+
quantitativeColorMax: quantitativeColorMaxSelected,
|
|
271516
|
+
pointsAreSegmentationCentroids
|
|
271113
271517
|
});
|
|
271114
271518
|
result = {
|
|
271115
271519
|
...result,
|
|
@@ -271122,7 +271526,13 @@ function useNeuroglancerViewerState(theme, showAxisLines, segmentationLayerScope
|
|
|
271122
271526
|
subsources: {
|
|
271123
271527
|
default: true
|
|
271124
271528
|
},
|
|
271125
|
-
enableDefaultSubsources: false
|
|
271529
|
+
enableDefaultSubsources: false,
|
|
271530
|
+
...ngOptions?.transform?.matrix ? {
|
|
271531
|
+
transform: {
|
|
271532
|
+
matrix: ngOptions.transform.matrix,
|
|
271533
|
+
outputDimensions: ngOptions.transform?.outputDimensions ?? result.dimensions
|
|
271534
|
+
}
|
|
271535
|
+
} : {}
|
|
271126
271536
|
},
|
|
271127
271537
|
tab: "annotations",
|
|
271128
271538
|
shader,
|
|
@@ -271130,7 +271540,7 @@ function useNeuroglancerViewerState(theme, showAxisLines, segmentationLayerScope
|
|
|
271130
271540
|
visible: spatialLayerVisible,
|
|
271131
271541
|
// Options from layerData.neuroglancerOptions
|
|
271132
271542
|
// like projectionAnnotationSpacing:
|
|
271133
|
-
projectionAnnotationSpacing:
|
|
271543
|
+
projectionAnnotationSpacing: ngOptions?.projectionAnnotationSpacing ?? 1
|
|
271134
271544
|
}
|
|
271135
271545
|
],
|
|
271136
271546
|
// TODO: is this needed?
|
|
@@ -271161,6 +271571,8 @@ function useNeuroglancerViewerState(theme, showAxisLines, segmentationLayerScope
|
|
|
271161
271571
|
}, customIsEqualForInitialViewerState);
|
|
271162
271572
|
return viewerState;
|
|
271163
271573
|
}
|
|
271574
|
+
const ANNOTATION_HEADER_OFFSET = 8;
|
|
271575
|
+
const GREY_HEX = "#323232";
|
|
271164
271576
|
const EPSILON_KEYS_MAPPING_NG = {
|
|
271165
271577
|
projectionScale: 100,
|
|
271166
271578
|
projectionOrientation: 0.02,
|
|
@@ -271181,6 +271593,17 @@ const multiplyQuat = (a2, b2) => {
|
|
|
271181
271593
|
const conjQuat = (q) => [-q[0], -q[1], -q[2], q[3]];
|
|
271182
271594
|
const rad2deg = (r3) => r3 * 180 / Math.PI;
|
|
271183
271595
|
const deg2rad = (d) => d * Math.PI / 180;
|
|
271596
|
+
function applyColormap(colormap, t4) {
|
|
271597
|
+
const tClamped = Math.max(0, Math.min(1, t4));
|
|
271598
|
+
const interpolators = {
|
|
271599
|
+
plasma: interpolatePlasma,
|
|
271600
|
+
viridis: interpolateViridis,
|
|
271601
|
+
jet: interpolateJet,
|
|
271602
|
+
greys: interpolateGreys
|
|
271603
|
+
};
|
|
271604
|
+
const fn2 = interpolators[colormap] ?? interpolateViridis;
|
|
271605
|
+
return fn2(tClamped);
|
|
271606
|
+
}
|
|
271184
271607
|
function valueGreaterThanEpsilon(a2, b2, epsilon3) {
|
|
271185
271608
|
if (Array.isArray(a2) && Array.isArray(b2) && a2.length === b2.length) {
|
|
271186
271609
|
return a2.some((val, i2) => Math.abs(val - b2[i2]) > epsilon3);
|
|
@@ -271247,13 +271670,57 @@ function makeVitNgZoomCalibrator(initialNgProjectionScale, initialDeckZoom = 0)
|
|
|
271247
271670
|
}
|
|
271248
271671
|
};
|
|
271249
271672
|
}
|
|
271673
|
+
function parseAnnotationChunkSegmentsWithPositions(buffer2, serializer2) {
|
|
271674
|
+
const dv = new DataView(buffer2);
|
|
271675
|
+
if (buffer2.byteLength <= 8)
|
|
271676
|
+
return [];
|
|
271677
|
+
const count2 = dv.getUint32(0, true);
|
|
271678
|
+
if (count2 === 0)
|
|
271679
|
+
return [];
|
|
271680
|
+
const numBytes = serializer2.serializedBytes;
|
|
271681
|
+
const properties2 = [null, null, null, null, null];
|
|
271682
|
+
const results = [];
|
|
271683
|
+
for (let i2 = 0; i2 < count2; i2++) {
|
|
271684
|
+
serializer2.deserialize(dv, ANNOTATION_HEADER_OFFSET, i2, count2, true, properties2);
|
|
271685
|
+
const phenotype = properties2[0];
|
|
271686
|
+
const segId = properties2[1];
|
|
271687
|
+
if (segId > 0) {
|
|
271688
|
+
const propBase = ANNOTATION_HEADER_OFFSET + i2 * numBytes;
|
|
271689
|
+
const x2 = dv.getFloat32(propBase + 0, true);
|
|
271690
|
+
const y2 = dv.getFloat32(propBase + 4, true);
|
|
271691
|
+
const z2 = dv.getFloat32(propBase + 8, true);
|
|
271692
|
+
if (x2 !== 0 || y2 !== 0 || z2 !== 0) {
|
|
271693
|
+
results.push({
|
|
271694
|
+
id: String(segId),
|
|
271695
|
+
// mesh segment ID - use for segments array
|
|
271696
|
+
phenotype: Number(phenotype),
|
|
271697
|
+
x: x2,
|
|
271698
|
+
y: y2,
|
|
271699
|
+
z: z2
|
|
271700
|
+
});
|
|
271701
|
+
}
|
|
271702
|
+
}
|
|
271703
|
+
}
|
|
271704
|
+
return results;
|
|
271705
|
+
}
|
|
271706
|
+
const remapCellColors = (ngCellColors, cellIdToMeshIdRef) => {
|
|
271707
|
+
const remapped = {};
|
|
271708
|
+
Object.entries(ngCellColors).forEach(([cellId, color2]) => {
|
|
271709
|
+
const meshId = cellIdToMeshIdRef.current[cellId] ?? cellId;
|
|
271710
|
+
remapped[meshId] = color2;
|
|
271711
|
+
});
|
|
271712
|
+
return remapped;
|
|
271713
|
+
};
|
|
271250
271714
|
const VITESSCE_INTERACTION_DELAY = 50;
|
|
271251
271715
|
const INIT_VIT_ZOOM = -3.6;
|
|
271252
271716
|
const ZOOM_EPS = 0.01;
|
|
271253
271717
|
const ROTATION_EPS = 1e-3;
|
|
271254
271718
|
const TARGET_EPS = 0.5;
|
|
271255
271719
|
const NG_ROT_COOLDOWN_MS = 120;
|
|
271720
|
+
const MESH_LOAD_THRESHOLD = 100;
|
|
271721
|
+
const MESH_LOADING_OVERLAY_TIMEOUT = 1500;
|
|
271256
271722
|
const GUIDE_URL = "https://vitessce.io/docs/ng-guide/";
|
|
271723
|
+
const MESH_OPACITY = 0.6;
|
|
271257
271724
|
const LAST_INTERACTION_SOURCE = {
|
|
271258
271725
|
vitessce: "vitessce",
|
|
271259
271726
|
neuroglancer: "neuroglancer"
|
|
@@ -271270,10 +271737,11 @@ function NeuroglancerSubscriber(props) {
|
|
|
271270
271737
|
downloadButtonVisible,
|
|
271271
271738
|
removeGridComponent,
|
|
271272
271739
|
theme,
|
|
271273
|
-
showAxisLines =
|
|
271740
|
+
showAxisLines = true,
|
|
271274
271741
|
title: title2 = "Spatial",
|
|
271275
271742
|
subtitle = "Powered by Neuroglancer",
|
|
271276
271743
|
helpText = ViewHelpMapping.NEUROGLANCER,
|
|
271744
|
+
meshLoadProjectionScaleThreshold,
|
|
271277
271745
|
// Note: this is a temporary mechanism
|
|
271278
271746
|
// to pass an initial NG camera state.
|
|
271279
271747
|
// Ideally, all camera state should be passed via
|
|
@@ -271284,6 +271752,32 @@ function NeuroglancerSubscriber(props) {
|
|
|
271284
271752
|
} = props;
|
|
271285
271753
|
const loaders = useLoaders();
|
|
271286
271754
|
const mergeCoordination = useMergeCoordination();
|
|
271755
|
+
const { classes: classes2 } = useStyles$4();
|
|
271756
|
+
const initialRotationPushedRef = useRef(false);
|
|
271757
|
+
const getViewProjectionMatRef = useRef(null);
|
|
271758
|
+
const obsIdToMeshIdRef = useRef({});
|
|
271759
|
+
const meshIdToCellIdRef = useRef({});
|
|
271760
|
+
const cellIdToMeshIdRef = useRef({});
|
|
271761
|
+
const ngRotPushAtRef = useRef(0);
|
|
271762
|
+
const lastInteractionSource = useRef(null);
|
|
271763
|
+
const applyNgUpdateTimeoutRef = useRef(null);
|
|
271764
|
+
const lastNgPushOrientationRef = useRef(null);
|
|
271765
|
+
const initialRenderCalibratorRef = useRef(null);
|
|
271766
|
+
const translationOffsetRef = useRef([0, 0, 0]);
|
|
271767
|
+
const zoomRafRef = useRef(null);
|
|
271768
|
+
const lastNgQuatRef = useRef([0, 0, 0, 1]);
|
|
271769
|
+
const lastNgScaleRef = useRef(null);
|
|
271770
|
+
const annotationInfoRef = useRef(null);
|
|
271771
|
+
const annotationTransformRef = useRef(null);
|
|
271772
|
+
const visibleSegmentIdsRef = useRef(null);
|
|
271773
|
+
const chunkCacheRef = useRef(/* @__PURE__ */ new Map());
|
|
271774
|
+
const resizeObserverRef = useRef(null);
|
|
271775
|
+
const [isLayersLoaded, setIsLayersLoaded] = useState(false);
|
|
271776
|
+
const [isMeshLoading, setIsMeshLoading] = useState(false);
|
|
271777
|
+
const [annotationReady, setAnnotationReady] = useState(false);
|
|
271778
|
+
const [csvLoaded, setCsvLoaded] = useState(false);
|
|
271779
|
+
const updateVisibleSegmentsThrottledRef = useRef(null);
|
|
271780
|
+
const viewportSizeRef = useRef({ width: 0, height: 0 });
|
|
271287
271781
|
const coordinationScopes = useCoordinationScopes(coordinationScopesRaw);
|
|
271288
271782
|
const coordinationScopesBy = useCoordinationScopesBy(coordinationScopes, coordinationScopesByRaw);
|
|
271289
271783
|
const [{
|
|
@@ -271315,6 +271809,19 @@ function NeuroglancerSubscriber(props) {
|
|
|
271315
271809
|
setSpatialRotationOrbit: setRotationOrbit,
|
|
271316
271810
|
setSpatialZoom: setZoom
|
|
271317
271811
|
}] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType$1.NEUROGLANCER], coordinationScopes);
|
|
271812
|
+
const csvUrlRef = useRef(null);
|
|
271813
|
+
const csvUrl = useMemo$1(() => {
|
|
271814
|
+
if (csvUrlRef.current)
|
|
271815
|
+
return csvUrlRef.current;
|
|
271816
|
+
const obsSetsMap = loaders?.[dataset]?.loaders?.obsSets;
|
|
271817
|
+
if (!obsSetsMap)
|
|
271818
|
+
return null;
|
|
271819
|
+
const firstLoader = obsSetsMap.values().next().value;
|
|
271820
|
+
const url = firstLoader?.url ?? null;
|
|
271821
|
+
if (url)
|
|
271822
|
+
csvUrlRef.current = url;
|
|
271823
|
+
return url;
|
|
271824
|
+
}, [loaders, dataset]);
|
|
271318
271825
|
const [ngWidth, ngHeight, containerRef] = useGridItemSize();
|
|
271319
271826
|
const [segmentationLayerScopes, segmentationChannelScopesByLayer] = useMultiCoordinationScopesSecondaryNonNull(CoordinationType$1.SEGMENTATION_CHANNEL, CoordinationType$1.SEGMENTATION_LAYER, coordinationScopes, coordinationScopesBy);
|
|
271320
271827
|
const pointLayerScopes = useMultiCoordinationScopesNonNull(CoordinationType$1.POINT_LAYER, coordinationScopes);
|
|
@@ -271343,7 +271850,9 @@ function NeuroglancerSubscriber(props) {
|
|
|
271343
271850
|
CoordinationType$1.OBS_HIGHLIGHT,
|
|
271344
271851
|
CoordinationType$1.TOOLTIPS_VISIBLE,
|
|
271345
271852
|
CoordinationType$1.TOOLTIP_CROSSHAIRS_VISIBLE,
|
|
271346
|
-
CoordinationType$1.LEGEND_VISIBLE
|
|
271853
|
+
CoordinationType$1.LEGEND_VISIBLE,
|
|
271854
|
+
CoordinationType$1.FEATURE_TYPE,
|
|
271855
|
+
CoordinationType$1.FEATURE_VALUE_TYPE
|
|
271347
271856
|
], coordinationScopes, coordinationScopesBy, CoordinationType$1.SEGMENTATION_LAYER, CoordinationType$1.SEGMENTATION_CHANNEL);
|
|
271348
271857
|
const pointLayerCoordination = useComplexCoordination([
|
|
271349
271858
|
CoordinationType$1.OBS_TYPE,
|
|
@@ -271360,7 +271869,10 @@ function NeuroglancerSubscriber(props) {
|
|
|
271360
271869
|
CoordinationType$1.TOOLTIPS_VISIBLE,
|
|
271361
271870
|
CoordinationType$1.TOOLTIP_CROSSHAIRS_VISIBLE,
|
|
271362
271871
|
CoordinationType$1.LEGEND_VISIBLE,
|
|
271363
|
-
CoordinationType$1.SPATIAL_POINT_STROKE_WIDTH
|
|
271872
|
+
CoordinationType$1.SPATIAL_POINT_STROKE_WIDTH,
|
|
271873
|
+
CoordinationType$1.OBS_SET_COLOR,
|
|
271874
|
+
CoordinationType$1.OBS_SET_SELECTION,
|
|
271875
|
+
CoordinationType$1.ADDITIONAL_OBS_SETS
|
|
271364
271876
|
], coordinationScopes, coordinationScopesBy, CoordinationType$1.POINT_LAYER);
|
|
271365
271877
|
const [obsPointsData, obsPointsDataStatus, obsPointsUrls, obsPointsErrors] = useMultiObsPoints(coordinationScopes, coordinationScopesBy, loaders, dataset, mergeCoordination, uuid2);
|
|
271366
271878
|
const [pointMultiIndicesData, pointMultiIndicesDataStatus, pointMultiIndicesDataErrors] = usePointMultiObsFeatureMatrixIndices(coordinationScopes, coordinationScopesBy, loaders, dataset);
|
|
@@ -271386,34 +271898,89 @@ function NeuroglancerSubscriber(props) {
|
|
|
271386
271898
|
segmentationMultiFeatureSelectionStatus,
|
|
271387
271899
|
segmentationMultiIndicesDataStatus
|
|
271388
271900
|
]);
|
|
271389
|
-
const
|
|
271901
|
+
const lastVitessceRotationRef = useRef({
|
|
271902
|
+
x: spatialRotationX,
|
|
271903
|
+
y: spatialRotationY,
|
|
271904
|
+
z: spatialRotationZ,
|
|
271905
|
+
orbit: spatialRotationOrbit
|
|
271906
|
+
});
|
|
271907
|
+
const prevCoordsRef = useRef({
|
|
271908
|
+
zoom: spatialZoom,
|
|
271909
|
+
rx: spatialRotationX,
|
|
271910
|
+
ry: spatialRotationY,
|
|
271911
|
+
rz: spatialRotationZ,
|
|
271912
|
+
orbit: spatialRotationOrbit,
|
|
271913
|
+
tx: spatialTargetX,
|
|
271914
|
+
ty: spatialTargetY
|
|
271915
|
+
});
|
|
271390
271916
|
const segmentationColorMapping = useMemoCustomComparison(() => {
|
|
271391
271917
|
const result = {};
|
|
271392
271918
|
segmentationLayerScopes?.forEach((layerScope) => {
|
|
271393
271919
|
result[layerScope] = {};
|
|
271394
271920
|
segmentationChannelScopesByLayer?.[layerScope]?.forEach((channelScope) => {
|
|
271395
|
-
const { obsSets: layerSets, obsIndex:
|
|
271396
|
-
const
|
|
271921
|
+
const { obsSets: layerSets, obsIndex: layerIndexFromSets } = obsSegmentationsSetsData?.[layerScope]?.[channelScope] || {};
|
|
271922
|
+
const layerIndex = layerIndexFromSets ?? null;
|
|
271923
|
+
const { obsSetColor, obsColorEncoding, obsSetSelection, additionalObsSets, spatialChannelColor, spatialChannelOpacity, featureValueColormap, featureValueColormapRange } = segmentationChannelCoordination[0][layerScope][channelScope];
|
|
271397
271924
|
if (obsColorEncoding === "spatialChannelColor") {
|
|
271398
|
-
if (
|
|
271925
|
+
if (spatialChannelColor) {
|
|
271399
271926
|
const hex2 = rgbToHex$1(spatialChannelColor);
|
|
271400
271927
|
const ngCellColors = {};
|
|
271401
|
-
if (
|
|
271402
|
-
|
|
271403
|
-
|
|
271404
|
-
|
|
271405
|
-
|
|
271406
|
-
|
|
271407
|
-
|
|
271408
|
-
|
|
271409
|
-
|
|
271410
|
-
|
|
271928
|
+
if (layerIndex) {
|
|
271929
|
+
if (obsSetSelection?.length > 0) {
|
|
271930
|
+
const mergedCellSets = mergeObsSets(layerSets, additionalObsSets);
|
|
271931
|
+
const selectedIds = /* @__PURE__ */ new Set();
|
|
271932
|
+
obsSetSelection.forEach((setPath) => {
|
|
271933
|
+
const rootNode = mergedCellSets?.tree?.find((n3) => n3.name === setPath[0]);
|
|
271934
|
+
const leafNode = setPath.length > 1 ? rootNode?.children?.find((n3) => n3.name === setPath[1]) : rootNode;
|
|
271935
|
+
leafNode?.set?.forEach(([id2]) => selectedIds.add(String(id2)));
|
|
271936
|
+
});
|
|
271937
|
+
layerIndex.forEach((id2) => {
|
|
271938
|
+
if (selectedIds.has(String(id2))) {
|
|
271939
|
+
ngCellColors[id2] = hex2;
|
|
271940
|
+
}
|
|
271941
|
+
});
|
|
271942
|
+
} else {
|
|
271943
|
+
layerIndex.forEach((id2) => {
|
|
271411
271944
|
ngCellColors[id2] = hex2;
|
|
271412
|
-
}
|
|
271413
|
-
}
|
|
271945
|
+
});
|
|
271946
|
+
}
|
|
271414
271947
|
}
|
|
271415
|
-
result[layerScope][channelScope] = ngCellColors;
|
|
271948
|
+
result[layerScope][channelScope] = remapCellColors(ngCellColors, cellIdToMeshIdRef);
|
|
271949
|
+
result[layerScope].opacity = spatialChannelOpacity ?? 1;
|
|
271950
|
+
result[layerScope].defaultColor = hex2;
|
|
271951
|
+
}
|
|
271952
|
+
} else if (obsColorEncoding === "geneSelection") {
|
|
271953
|
+
const instanceObsIndex = obsSegmentationsSetsData?.[layerScope]?.[channelScope]?.obsIndex;
|
|
271954
|
+
const matrixObsIndex = segmentationMultiIndicesData?.[layerScope]?.[channelScope]?.obsIndex;
|
|
271955
|
+
const expressionData = segmentationMultiExpressionNormData?.[layerScope]?.[channelScope];
|
|
271956
|
+
if (instanceObsIndex && matrixObsIndex && expressionData?.[0]) {
|
|
271957
|
+
const matrixIndexMap = new Map(matrixObsIndex.map((key2, i2) => {
|
|
271958
|
+
const normalizedKey = key2.replace(/^.*_/, "");
|
|
271959
|
+
return [normalizedKey, i2];
|
|
271960
|
+
}));
|
|
271961
|
+
const toMatrixIndex = instanceObsIndex.map((key2) => matrixIndexMap.get(String(key2)));
|
|
271962
|
+
const [low, high] = featureValueColormapRange ?? [0, 1];
|
|
271963
|
+
const ngCellColors = {};
|
|
271964
|
+
instanceObsIndex.forEach((id2, i2) => {
|
|
271965
|
+
const rowIndex = toMatrixIndex[i2];
|
|
271966
|
+
const rawVal = expressionData[0][rowIndex] ?? 0;
|
|
271967
|
+
const t4 = rawVal / 255;
|
|
271968
|
+
const tScaled = (t4 - low) / Math.max(high - low, 1e-4);
|
|
271969
|
+
const tClamped = Math.max(0, Math.min(1, tScaled));
|
|
271970
|
+
const color2 = applyColormap(featureValueColormap ?? "viridis", tClamped);
|
|
271971
|
+
ngCellColors[id2] = rgbToHex$1(color2);
|
|
271972
|
+
});
|
|
271973
|
+
result[layerScope][channelScope] = remapCellColors(ngCellColors, cellIdToMeshIdRef);
|
|
271974
|
+
result[layerScope].opacity = spatialChannelOpacity ?? 1;
|
|
271975
|
+
} else if (instanceObsIndex) {
|
|
271976
|
+
const fallbackColor = spatialChannelColor ? rgbToHex$1(spatialChannelColor) : GREY_HEX;
|
|
271977
|
+
const ngCellColors = {};
|
|
271978
|
+
instanceObsIndex.forEach((id2) => {
|
|
271979
|
+
ngCellColors[id2] = fallbackColor;
|
|
271980
|
+
});
|
|
271981
|
+
result[layerScope][channelScope] = remapCellColors(ngCellColors, cellIdToMeshIdRef);
|
|
271416
271982
|
result[layerScope].opacity = spatialChannelOpacity ?? 1;
|
|
271983
|
+
result[layerScope].defaultColor = fallbackColor;
|
|
271417
271984
|
}
|
|
271418
271985
|
} else if (layerSets && layerIndex) {
|
|
271419
271986
|
const mergedCellSets = mergeObsSets(layerSets, additionalObsSets);
|
|
@@ -271425,10 +271992,10 @@ function NeuroglancerSubscriber(props) {
|
|
|
271425
271992
|
theme
|
|
271426
271993
|
});
|
|
271427
271994
|
const ngCellColors = {};
|
|
271428
|
-
cellColors.forEach((color2,
|
|
271429
|
-
ngCellColors[
|
|
271995
|
+
cellColors.forEach((color2, id2) => {
|
|
271996
|
+
ngCellColors[id2] = rgbToHex$1(color2);
|
|
271430
271997
|
});
|
|
271431
|
-
result[layerScope][channelScope] = ngCellColors;
|
|
271998
|
+
result[layerScope][channelScope] = remapCellColors(ngCellColors, cellIdToMeshIdRef);
|
|
271432
271999
|
result[layerScope].opacity = spatialChannelOpacity ?? 1;
|
|
271433
272000
|
}
|
|
271434
272001
|
});
|
|
@@ -271441,14 +272008,201 @@ function NeuroglancerSubscriber(props) {
|
|
|
271441
272008
|
segmentationChannelScopesByLayer,
|
|
271442
272009
|
obsSegmentationsSetsData,
|
|
271443
272010
|
segmentationChannelCoordination,
|
|
271444
|
-
theme
|
|
272011
|
+
theme,
|
|
272012
|
+
segmentationMultiExpressionNormData,
|
|
272013
|
+
segmentationMultiIndicesData,
|
|
272014
|
+
csvLoaded
|
|
271445
272015
|
}, customIsEqualForCellColors);
|
|
271446
|
-
const
|
|
272016
|
+
const initialViewerState = useNeuroglancerViewerState(theme, showAxisLines, segmentationLayerScopes, segmentationChannelScopesByLayer, segmentationLayerCoordination, segmentationChannelCoordination, obsSegmentationsUrls, obsSegmentationsData, pointLayerScopes, pointLayerCoordination, obsPointsUrls, obsPointsData, pointMultiIndicesData);
|
|
271447
272017
|
const [latestViewerStateIteration, incrementLatestViewerStateIteration] = useReducer((x2) => x2 + 1, 0);
|
|
271448
272018
|
const latestViewerStateRef = useRef({
|
|
271449
|
-
...
|
|
272019
|
+
...initialViewerState,
|
|
271450
272020
|
...initialNgCameraState ?? {}
|
|
271451
272021
|
});
|
|
272022
|
+
useEffect(() => {
|
|
272023
|
+
if (!csvUrl)
|
|
272024
|
+
return;
|
|
272025
|
+
fetch(csvUrl).then((r3) => r3.text()).then((text2) => {
|
|
272026
|
+
const lines = text2.split("\n");
|
|
272027
|
+
const header = lines[0].split(",");
|
|
272028
|
+
const meshIdIdx = header.indexOf("MeshID");
|
|
272029
|
+
const cellIdIdx = header.indexOf("CellID");
|
|
272030
|
+
const meshMap = {};
|
|
272031
|
+
const cellMap = {};
|
|
272032
|
+
lines.slice(1).forEach((l2) => {
|
|
272033
|
+
const cols = l2.split(",");
|
|
272034
|
+
const meshId = cols[meshIdIdx]?.trim();
|
|
272035
|
+
const cellId = cols[cellIdIdx]?.trim();
|
|
272036
|
+
if (meshId && cellId) {
|
|
272037
|
+
meshMap[meshId] = cellId;
|
|
272038
|
+
cellMap[cellId] = meshId;
|
|
272039
|
+
}
|
|
272040
|
+
});
|
|
272041
|
+
meshIdToCellIdRef.current = meshMap;
|
|
272042
|
+
cellIdToMeshIdRef.current = cellMap;
|
|
272043
|
+
setCsvLoaded(true);
|
|
272044
|
+
});
|
|
272045
|
+
}, [csvUrl]);
|
|
272046
|
+
useEffect(() => {
|
|
272047
|
+
chunkCacheRef.current.clear();
|
|
272048
|
+
}, [obsPointsData]);
|
|
272049
|
+
useEffect(() => {
|
|
272050
|
+
if (ngWidth && ngHeight) {
|
|
272051
|
+
viewportSizeRef.current = { width: ngWidth, height: ngHeight };
|
|
272052
|
+
}
|
|
272053
|
+
}, [ngWidth, ngHeight]);
|
|
272054
|
+
const setContainerNode = useCallback((node2) => {
|
|
272055
|
+
containerRef.current = node2;
|
|
272056
|
+
if (resizeObserverRef.current) {
|
|
272057
|
+
resizeObserverRef.current.disconnect();
|
|
272058
|
+
resizeObserverRef.current = null;
|
|
272059
|
+
}
|
|
272060
|
+
if (node2) {
|
|
272061
|
+
const rect2 = node2.getBoundingClientRect();
|
|
272062
|
+
if (rect2.width && rect2.height) {
|
|
272063
|
+
viewportSizeRef.current = { width: rect2.width, height: rect2.height };
|
|
272064
|
+
}
|
|
272065
|
+
const observer2 = new ResizeObserver((entries2) => {
|
|
272066
|
+
const entry2 = entries2[0];
|
|
272067
|
+
if (!entry2)
|
|
272068
|
+
return;
|
|
272069
|
+
const { width: width2, height: height2 } = entry2.contentRect;
|
|
272070
|
+
if (width2 && height2) {
|
|
272071
|
+
viewportSizeRef.current = { width: width2, height: height2 };
|
|
272072
|
+
}
|
|
272073
|
+
});
|
|
272074
|
+
observer2.observe(node2);
|
|
272075
|
+
resizeObserverRef.current = observer2;
|
|
272076
|
+
}
|
|
272077
|
+
}, []);
|
|
272078
|
+
const updateVisibleSegments = useCallback(async () => {
|
|
272079
|
+
if (!annotationInfoRef.current)
|
|
272080
|
+
return;
|
|
272081
|
+
if (!annotationTransformRef.current)
|
|
272082
|
+
return;
|
|
272083
|
+
if (!segmentationLayerScopes?.length)
|
|
272084
|
+
return;
|
|
272085
|
+
if (!pointLayerScopes?.length)
|
|
272086
|
+
return;
|
|
272087
|
+
const { position: position2, projectionScale } = latestViewerStateRef.current;
|
|
272088
|
+
if (!position2 || !projectionScale)
|
|
272089
|
+
return;
|
|
272090
|
+
const maxProjectionScale = meshLoadProjectionScaleThreshold ?? MESH_LOAD_THRESHOLD;
|
|
272091
|
+
if (projectionScale > maxProjectionScale) {
|
|
272092
|
+
if (visibleSegmentIdsRef.current?.length !== 0) {
|
|
272093
|
+
visibleSegmentIdsRef.current = [];
|
|
272094
|
+
incrementLatestViewerStateIteration();
|
|
272095
|
+
setIsMeshLoading(false);
|
|
272096
|
+
}
|
|
272097
|
+
return;
|
|
272098
|
+
}
|
|
272099
|
+
const { width: width2, height: height2 } = viewportSizeRef.current;
|
|
272100
|
+
if (!width2 || !height2)
|
|
272101
|
+
return;
|
|
272102
|
+
const transform3 = annotationTransformRef.current;
|
|
272103
|
+
const info2 = annotationInfoRef.current;
|
|
272104
|
+
const cellsUrl2 = info2.url;
|
|
272105
|
+
const allLevelCoords = info2.spatial.flatMap((level) => {
|
|
272106
|
+
const [gx, gy, gz] = level.grid_shape;
|
|
272107
|
+
const coords = [];
|
|
272108
|
+
for (let cx = 0; cx < gx; cx++) {
|
|
272109
|
+
for (let cy = 0; cy < gy; cy++) {
|
|
272110
|
+
for (let cz = 0; cz < gz; cz++) {
|
|
272111
|
+
coords.push({ level: level.key, cx, cy, cz });
|
|
272112
|
+
}
|
|
272113
|
+
}
|
|
272114
|
+
}
|
|
272115
|
+
return coords;
|
|
272116
|
+
});
|
|
272117
|
+
const fetchChunkWithPositions = async ({ level, cx, cy, cz }) => {
|
|
272118
|
+
const { serializers, serializer: defaultSerializer } = annotationTransformRef.current;
|
|
272119
|
+
const serializer2 = serializers?.[0] ?? defaultSerializer;
|
|
272120
|
+
if (!serializer2)
|
|
272121
|
+
return [];
|
|
272122
|
+
const cacheKey = `${cellsUrl2}/${level}/${cx}_${cy}_${cz}`;
|
|
272123
|
+
if (chunkCacheRef.current.has(cacheKey)) {
|
|
272124
|
+
return chunkCacheRef.current.get(cacheKey);
|
|
272125
|
+
}
|
|
272126
|
+
try {
|
|
272127
|
+
const res = await fetch(cacheKey);
|
|
272128
|
+
if (!res.ok) {
|
|
272129
|
+
chunkCacheRef.current.set(cacheKey, []);
|
|
272130
|
+
return [];
|
|
272131
|
+
}
|
|
272132
|
+
const buffer2 = await res.arrayBuffer();
|
|
272133
|
+
const entries2 = parseAnnotationChunkSegmentsWithPositions(buffer2, serializer2);
|
|
272134
|
+
chunkCacheRef.current.set(cacheKey, entries2);
|
|
272135
|
+
return entries2;
|
|
272136
|
+
} catch (e3) {
|
|
272137
|
+
chunkCacheRef.current.set(cacheKey, []);
|
|
272138
|
+
return [];
|
|
272139
|
+
}
|
|
272140
|
+
};
|
|
272141
|
+
try {
|
|
272142
|
+
const results = await Promise.all(allLevelCoords.map(fetchChunkWithPositions));
|
|
272143
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
272144
|
+
const allEntries = results.flat().filter(({ id: id2 }) => {
|
|
272145
|
+
if (seenIds.has(id2))
|
|
272146
|
+
return false;
|
|
272147
|
+
seenIds.add(id2);
|
|
272148
|
+
return true;
|
|
272149
|
+
});
|
|
272150
|
+
const obsIdToMeshId = {};
|
|
272151
|
+
allEntries.forEach(({ id: id2, obsId }) => {
|
|
272152
|
+
obsIdToMeshId[obsId] = id2;
|
|
272153
|
+
});
|
|
272154
|
+
obsIdToMeshIdRef.current = obsIdToMeshId;
|
|
272155
|
+
const mat = getViewProjectionMatRef.current?.();
|
|
272156
|
+
let visibleIds;
|
|
272157
|
+
if (!mat) {
|
|
272158
|
+
console.warn("No viewProjectionMatrix, loading all");
|
|
272159
|
+
visibleIds = [...new Set(allEntries.map(({ id: id2 }) => id2))];
|
|
272160
|
+
} else {
|
|
272161
|
+
const margin2 = Math.max(width2, height2) * 0.5;
|
|
272162
|
+
visibleIds = [...new Set(allEntries.filter(({ x: x2, y: y2, z: z2 }) => {
|
|
272163
|
+
const vx = x2 / transform3.x;
|
|
272164
|
+
const vy = y2 / transform3.y;
|
|
272165
|
+
const vz = (z2 || 0) / transform3.z;
|
|
272166
|
+
const cx = mat[0] * vx + mat[4] * vy + mat[8] * vz + mat[12];
|
|
272167
|
+
const cy = mat[1] * vx + mat[5] * vy + mat[9] * vz + mat[13];
|
|
272168
|
+
const cw2 = mat[3] * vx + mat[7] * vy + mat[11] * vz + mat[15];
|
|
272169
|
+
const screenX = (cx / cw2 + 1) * 0.5 * width2;
|
|
272170
|
+
const screenY = (1 - cy / cw2) * 0.5 * height2;
|
|
272171
|
+
return screenX >= -margin2 && screenX <= width2 + margin2 && screenY >= -margin2 && screenY <= height2 + margin2;
|
|
272172
|
+
}).map(({ id: id2 }) => id2))];
|
|
272173
|
+
}
|
|
272174
|
+
if (visibleIds.length === 0) {
|
|
272175
|
+
if (visibleSegmentIdsRef.current?.length !== 0) {
|
|
272176
|
+
visibleSegmentIdsRef.current = [];
|
|
272177
|
+
incrementLatestViewerStateIteration();
|
|
272178
|
+
}
|
|
272179
|
+
setIsMeshLoading(false);
|
|
272180
|
+
return;
|
|
272181
|
+
}
|
|
272182
|
+
const prevIds = new Set(visibleSegmentIdsRef.current ?? []);
|
|
272183
|
+
const addedIdsCount = visibleIds.filter((id2) => !prevIds.has(id2)).length;
|
|
272184
|
+
const hasSignificantChange = addedIdsCount > 20;
|
|
272185
|
+
if (hasSignificantChange && visibleIds.length > 0) {
|
|
272186
|
+
setIsMeshLoading(true);
|
|
272187
|
+
}
|
|
272188
|
+
const prevSorted = [...visibleSegmentIdsRef.current ?? []].sort().join(",");
|
|
272189
|
+
const nextSorted = [...visibleIds].sort().join(",");
|
|
272190
|
+
if (prevSorted !== nextSorted) {
|
|
272191
|
+
visibleSegmentIdsRef.current = visibleIds;
|
|
272192
|
+
incrementLatestViewerStateIteration();
|
|
272193
|
+
}
|
|
272194
|
+
if (hasSignificantChange) {
|
|
272195
|
+
setTimeout(() => setIsMeshLoading(false), MESH_LOADING_OVERLAY_TIMEOUT);
|
|
272196
|
+
}
|
|
272197
|
+
} catch (e3) {
|
|
272198
|
+
console.warn("[updateVisibleSegments] error:", e3);
|
|
272199
|
+
setIsMeshLoading(false);
|
|
272200
|
+
}
|
|
272201
|
+
}, [segmentationLayerScopes, pointLayerScopes, obsPointsData, meshLoadProjectionScaleThreshold]);
|
|
272202
|
+
useEffect(() => {
|
|
272203
|
+
updateVisibleSegmentsThrottledRef.current = throttle$1(updateVisibleSegments, 500);
|
|
272204
|
+
return () => updateVisibleSegmentsThrottledRef.current?.cancel();
|
|
272205
|
+
}, [updateVisibleSegments]);
|
|
271452
272206
|
useEffect(() => {
|
|
271453
272207
|
const prevNgCameraState = {
|
|
271454
272208
|
position: latestViewerStateRef.current.position,
|
|
@@ -271456,37 +272210,50 @@ function NeuroglancerSubscriber(props) {
|
|
|
271456
272210
|
projectionScale: latestViewerStateRef.current.projectionScale
|
|
271457
272211
|
};
|
|
271458
272212
|
latestViewerStateRef.current = {
|
|
271459
|
-
...
|
|
272213
|
+
...initialViewerState,
|
|
271460
272214
|
...prevNgCameraState
|
|
271461
272215
|
};
|
|
271462
272216
|
incrementLatestViewerStateIteration();
|
|
271463
|
-
}, [
|
|
271464
|
-
const
|
|
271465
|
-
|
|
271466
|
-
|
|
271467
|
-
|
|
271468
|
-
const
|
|
271469
|
-
|
|
271470
|
-
|
|
271471
|
-
|
|
271472
|
-
|
|
271473
|
-
|
|
271474
|
-
|
|
271475
|
-
|
|
271476
|
-
|
|
271477
|
-
|
|
271478
|
-
|
|
271479
|
-
|
|
271480
|
-
|
|
271481
|
-
|
|
271482
|
-
|
|
271483
|
-
|
|
271484
|
-
|
|
271485
|
-
|
|
271486
|
-
|
|
271487
|
-
|
|
271488
|
-
|
|
271489
|
-
|
|
272217
|
+
}, [initialViewerState]);
|
|
272218
|
+
const cellsUrl = useMemo$1(() => {
|
|
272219
|
+
const firstScope = pointLayerScopes?.[0];
|
|
272220
|
+
return obsPointsUrls?.[firstScope]?.[0]?.url ?? null;
|
|
272221
|
+
}, [pointLayerScopes, obsPointsUrls]);
|
|
272222
|
+
const hasMatchingAnnotationSource = useMemo$1(() => {
|
|
272223
|
+
if (!cellsUrl)
|
|
272224
|
+
return false;
|
|
272225
|
+
const firstPointScope = pointLayerScopes?.[0];
|
|
272226
|
+
return pointsHaveMatchingSegmentation({
|
|
272227
|
+
pointObsType: pointLayerCoordination[0]?.[firstPointScope]?.obsType,
|
|
272228
|
+
segmentationLayerScopes,
|
|
272229
|
+
segmentationChannelScopesByLayer,
|
|
272230
|
+
segmentationChannelCoordination
|
|
272231
|
+
});
|
|
272232
|
+
}, [cellsUrl, pointLayerScopes, segmentationLayerScopes, segmentationChannelScopesByLayer]);
|
|
272233
|
+
useEffect(() => {
|
|
272234
|
+
if (!cellsUrl)
|
|
272235
|
+
return;
|
|
272236
|
+
fetch(`${cellsUrl}/info`).then((r3) => r3.json()).then((info2) => {
|
|
272237
|
+
const infoWithUrl = {
|
|
272238
|
+
...info2,
|
|
272239
|
+
url: cellsUrl
|
|
272240
|
+
};
|
|
272241
|
+
annotationInfoRef.current = infoWithUrl;
|
|
272242
|
+
if (annotationTransformRef.current)
|
|
272243
|
+
setAnnotationReady(true);
|
|
272244
|
+
}).catch((err2) => console.error("failed to fetch annotation info:", err2));
|
|
272245
|
+
}, [cellsUrl]);
|
|
272246
|
+
useEffect(() => {
|
|
272247
|
+
if (annotationReady) {
|
|
272248
|
+
setIsLayersLoaded(true);
|
|
272249
|
+
updateVisibleSegments();
|
|
272250
|
+
}
|
|
272251
|
+
}, [annotationReady]);
|
|
272252
|
+
const onAnnotationSourceReady = useCallback((transform3) => {
|
|
272253
|
+
annotationTransformRef.current = transform3;
|
|
272254
|
+
if (annotationInfoRef.current)
|
|
272255
|
+
setAnnotationReady(true);
|
|
272256
|
+
}, []);
|
|
271490
272257
|
const handleStateUpdate = useCallback((newState) => {
|
|
271491
272258
|
lastInteractionSource.current = LAST_INTERACTION_SOURCE.neuroglancer;
|
|
271492
272259
|
const { projectionScale, projectionOrientation, position: position2 } = newState;
|
|
@@ -271519,6 +272286,7 @@ function NeuroglancerSubscriber(props) {
|
|
|
271519
272286
|
setZoom(vitZoomFromNg);
|
|
271520
272287
|
zoomRafRef.current = null;
|
|
271521
272288
|
});
|
|
272289
|
+
updateVisibleSegments();
|
|
271522
272290
|
}
|
|
271523
272291
|
lastNgScaleRef.current = projectionScale;
|
|
271524
272292
|
}
|
|
@@ -271559,7 +272327,8 @@ function NeuroglancerSubscriber(props) {
|
|
|
271559
272327
|
projectionScale,
|
|
271560
272328
|
position: position2
|
|
271561
272329
|
};
|
|
271562
|
-
|
|
272330
|
+
updateVisibleSegmentsThrottledRef.current?.();
|
|
272331
|
+
}, [updateVisibleSegmentsThrottledRef]);
|
|
271563
272332
|
const onSegmentClick = useCallback((value2) => {
|
|
271564
272333
|
if (value2) {
|
|
271565
272334
|
const id2 = String(value2);
|
|
@@ -271584,11 +272353,18 @@ function NeuroglancerSubscriber(props) {
|
|
|
271584
272353
|
const channelScope = segmentationChannelScopesByLayer?.[layerScope]?.[0];
|
|
271585
272354
|
result[layerScope] = {
|
|
271586
272355
|
colors: segmentationColorMapping?.[layerScope]?.[channelScope] ?? {},
|
|
271587
|
-
opacity: segmentationColorMapping?.[layerScope]?.opacity ?? 1
|
|
272356
|
+
opacity: segmentationColorMapping?.[layerScope]?.opacity ?? 1,
|
|
272357
|
+
defaultColor: segmentationColorMapping?.[layerScope]?.defaultColor ?? null
|
|
271588
272358
|
};
|
|
271589
272359
|
});
|
|
271590
272360
|
return result;
|
|
271591
272361
|
}, [segmentationColorMapping, segmentationLayerScopes, segmentationChannelScopesByLayer]);
|
|
272362
|
+
useEffect(() => {
|
|
272363
|
+
if (!hasMatchingAnnotationSource && isReady && !segmentationLayerScopes?.length) {
|
|
272364
|
+
setIsLayersLoaded(true);
|
|
272365
|
+
}
|
|
272366
|
+
}, [hasMatchingAnnotationSource, isReady, segmentationLayerScopes]);
|
|
272367
|
+
const meshOpacity = hasMatchingAnnotationSource ? MESH_OPACITY : void 0;
|
|
271592
272368
|
const derivedViewerState = useMemo$1(() => {
|
|
271593
272369
|
const { current: current2 } = latestViewerStateRef;
|
|
271594
272370
|
if (current2.layers.length <= 0) {
|
|
@@ -271647,13 +272423,33 @@ function NeuroglancerSubscriber(props) {
|
|
|
271647
272423
|
lastInteractionSource.current = null;
|
|
271648
272424
|
}
|
|
271649
272425
|
const updatedLayers = current2?.layers?.map((layer, idx) => {
|
|
271650
|
-
|
|
272426
|
+
if (layer.type !== "segmentation")
|
|
272427
|
+
return layer;
|
|
272428
|
+
const layerScope = segmentationLayerScopes?.find((scope) => layer.name?.includes(scope));
|
|
272429
|
+
if (!layerScope)
|
|
272430
|
+
return layer;
|
|
271651
272431
|
const layerColorMapping = cellColorMappingByLayer?.[layerScope]?.colors ?? {};
|
|
271652
|
-
const
|
|
272432
|
+
const defaultColor = cellColorMappingByLayer?.[layerScope]?.defaultColor;
|
|
272433
|
+
let segments2 = [];
|
|
272434
|
+
if (hasMatchingAnnotationSource) {
|
|
272435
|
+
segments2 = visibleSegmentIdsRef.current ?? [];
|
|
272436
|
+
} else if (Object.keys(layerColorMapping).length > 0) {
|
|
272437
|
+
segments2 = Object.keys(layerColorMapping);
|
|
272438
|
+
}
|
|
272439
|
+
let derivedSegmentColors = {};
|
|
272440
|
+
if (hasMatchingAnnotationSource && segments2.length > 0) {
|
|
272441
|
+
segments2.forEach((meshId) => {
|
|
272442
|
+
const color2 = layerColorMapping[meshId] || defaultColor;
|
|
272443
|
+
if (color2)
|
|
272444
|
+
derivedSegmentColors[meshId] = color2;
|
|
272445
|
+
});
|
|
272446
|
+
} else if (!hasMatchingAnnotationSource) {
|
|
272447
|
+
derivedSegmentColors = layerColorMapping;
|
|
272448
|
+
}
|
|
271653
272449
|
return {
|
|
271654
272450
|
...layer,
|
|
271655
|
-
segments:
|
|
271656
|
-
segmentColors:
|
|
272451
|
+
segments: segments2,
|
|
272452
|
+
segmentColors: derivedSegmentColors,
|
|
271657
272453
|
objectAlpha: cellColorMappingByLayer?.[layerScope]?.opacity ?? 1
|
|
271658
272454
|
};
|
|
271659
272455
|
}) ?? [];
|
|
@@ -271683,17 +272479,21 @@ function NeuroglancerSubscriber(props) {
|
|
|
271683
272479
|
spatialRotationZ,
|
|
271684
272480
|
spatialTargetX,
|
|
271685
272481
|
spatialTargetY,
|
|
271686
|
-
|
|
271687
|
-
latestViewerStateIteration
|
|
272482
|
+
initialViewerState,
|
|
272483
|
+
latestViewerStateIteration,
|
|
272484
|
+
hasMatchingAnnotationSource
|
|
271688
272485
|
]);
|
|
271689
272486
|
const onSegmentHighlight = useCallback((obsId) => {
|
|
271690
272487
|
setCellHighlight(String(obsId));
|
|
271691
272488
|
}, [setCellHighlight]);
|
|
271692
272489
|
const handleLayerLoadingChange = useCallback((isLoaded) => {
|
|
271693
|
-
|
|
271694
|
-
|
|
272490
|
+
if (!isLayersLoaded && isLoaded) {
|
|
272491
|
+
setIsLayersLoaded(true);
|
|
272492
|
+
}
|
|
272493
|
+
}, [isLayersLoaded]);
|
|
271695
272494
|
const hasLayers = derivedViewerState?.layers?.length > 0;
|
|
271696
|
-
|
|
272495
|
+
const showPointsLegend = !hasMatchingAnnotationSource;
|
|
272496
|
+
return jsx$1(TitleInfo, { title: title2, info: subtitle, helpText, isSpatial: true, theme, closeButtonVisible, downloadButtonVisible, removeGridComponent, isReady: isReady && isLayersLoaded, errors, withPadding: false, guideUrl: GUIDE_URL, children: hasLayers ? jsxs("div", { style: { position: "relative", width: "100%", height: "100%" }, ref: setContainerNode, children: [jsx$1("div", { style: { position: "absolute", top: 0, right: 0, zIndex: 50 }, children: jsx$1(MultiLegend, {
|
|
271697
272497
|
theme: "dark",
|
|
271698
272498
|
maxHeight: ngHeight,
|
|
271699
272499
|
// Segmentations
|
|
@@ -271702,10 +272502,12 @@ function NeuroglancerSubscriber(props) {
|
|
|
271702
272502
|
segmentationChannelScopesByLayer,
|
|
271703
272503
|
segmentationChannelCoordination,
|
|
271704
272504
|
// Points
|
|
271705
|
-
pointLayerScopes,
|
|
272505
|
+
pointLayerScopes: showPointsLegend ? pointLayerScopes : void 0,
|
|
271706
272506
|
pointLayerCoordination,
|
|
271707
272507
|
pointMultiIndicesData
|
|
271708
|
-
}) }), jsx$1(NeuroglancerComp, { classes: classes2, onSegmentClick, onSelectHoveredCoords: onSegmentHighlight, viewerState: derivedViewerState, cellColorMapping: cellColorMappingByLayer, setViewerState: handleStateUpdate, onLayerLoadingChange: handleLayerLoadingChange
|
|
272508
|
+
}) }), isMeshLoading ? jsx$1(Chip, { label: "Loading meshes...", size: "small", color: "primary", className: classes2.meshLoadingIndicator }) : null, jsx$1(NeuroglancerComp, { classes: classes2, onSegmentClick, onSelectHoveredCoords: onSegmentHighlight, viewerState: derivedViewerState, cellColorMapping: cellColorMappingByLayer, setViewerState: handleStateUpdate, onLayerLoadingChange: handleLayerLoadingChange, onAnnotationSourceReady, onViewerReady: (getFn) => {
|
|
272509
|
+
getViewProjectionMatRef.current = getFn;
|
|
272510
|
+
}, getMeshIdToCellId: (meshId) => meshIdToCellIdRef.current[meshId], cellsUrl, meshOpacity })] }) : null });
|
|
271709
272511
|
}
|
|
271710
272512
|
const FEATURE_AGGREGATION_STRATEGIES = ["first", "last", "sum", "mean"];
|
|
271711
272513
|
function CellSetExpressionPlotOptions(props) {
|
|
@@ -273544,7 +274346,7 @@ function useFilteredVolcanoData(props) {
|
|
|
273544
274346
|
const rawSampleSetPathB = coordinationValues.sampleSetFilter[1];
|
|
273545
274347
|
const sampleSetPathB = [...rawSampleSetPathB];
|
|
273546
274348
|
sampleSetPathB[0] = sampleSetsColumnNameMappingReversed[rawSampleSetPathB[0]];
|
|
273547
|
-
if (isEqual$3(sampleSetPathA, sampleSetSelection[
|
|
274349
|
+
if (isEqual$3(sampleSetPathA, sampleSetSelection[0]) && isEqual$3(sampleSetPathB, sampleSetSelection[1])) {
|
|
273548
274350
|
shouldSwapFoldChangeDirection = true;
|
|
273549
274351
|
}
|
|
273550
274352
|
}
|
|
@@ -324203,7 +325005,7 @@ const VEGA_THEMES = {
|
|
|
324203
325005
|
};
|
|
324204
325006
|
const DATASET_NAME = "table";
|
|
324205
325007
|
function VegaGlobalStyles() {
|
|
324206
|
-
const { theme } = useStyles$
|
|
325008
|
+
const { theme } = useStyles$y();
|
|
324207
325009
|
return jsx$1(GlobalStyles$3, { styles: {
|
|
324208
325010
|
"#vg-tooltip-element.vg-tooltip.custom-theme": {
|
|
324209
325011
|
boxShadow: "0px 2px 4px -1px rgba(0,0,0,0.2),0px 4px 5px 0px rgba(0,0,0,0.14),0px 1px 10px 0px rgba(0,0,0,0.12)",
|
|
@@ -324237,7 +325039,7 @@ function renderTooltipContents(tooltipText) {
|
|
|
324237
325039
|
}
|
|
324238
325040
|
function VegaPlot(props) {
|
|
324239
325041
|
const { spec: partialSpec, data: data2, getTooltipText, signalListeners, renderer = "svg", onNewView } = props;
|
|
324240
|
-
const { classes: tooltipClasses2 } = useStyles$
|
|
325042
|
+
const { classes: tooltipClasses2 } = useStyles$t();
|
|
324241
325043
|
const tooltipHandler = useMemo$1(() => {
|
|
324242
325044
|
if (typeof getTooltipText === "function") {
|
|
324243
325045
|
const tooltipConfig = {
|
|
@@ -325298,6 +326100,10 @@ function TreemapSubscriber(props) {
|
|
|
325298
326100
|
}, [setObsSetSelection]);
|
|
325299
326101
|
return jsxs(TitleInfo, { title: `Treemap of ${capitalize$3(pluralize(obsType, 2))}`, info: `${commaNumber(selectedObsCount)} ${pluralize(obsType, selectedObsCount)} from ${commaNumber(selectedSampleCount)} ${pluralize(sampleType, selectedSampleCount)}`, removeGridComponent, urls: urls2, theme, isReady, helpText, errors, withPadding: false, options: jsx$1(TreemapOptions, { obsType, sampleType, obsColorEncoding, setObsColorEncoding, hierarchyLevels: hierarchyLevels || DEFAULT_HIERARCHY_LEVELS, setHierarchyLevels }), children: [jsx$1("div", { ref: containerRef, className: classes2.vegaContainer, children: jsx$1(Treemap, { obsCounts, sampleCounts, obsColorEncoding, hierarchyLevels: hierarchyLevels || DEFAULT_HIERARCHY_LEVELS, theme, width: width2, height: Math.max(height2 * (selectedObsCount / totalObsCount), 40), obsType, sampleType, obsSetColor, sampleSetColor, obsSetSelection, sampleSetSelection, onNodeClick }) }), jsx$1("div", { style: { position: "absolute", right: "2px", bottom: "2px", fontSize: "10px" }, children: unselectedObsCount > 0 ? jsx$1("span", { children: `${commaNumber(unselectedObsCount)} ${pluralize(obsType, unselectedObsCount)} from ${commaNumber(unselectedSampleCount)} ${pluralize(sampleType, unselectedSampleCount)} currently omitted` }) : null })] });
|
|
325300
326102
|
}
|
|
326103
|
+
const GOLDEN_RATIO = 0.6180339887498948;
|
|
326104
|
+
function topJitter(index2, rangePixels) {
|
|
326105
|
+
return index2 * GOLDEN_RATIO % 1 * rangePixels;
|
|
326106
|
+
}
|
|
325301
326107
|
function VolcanoPlot(props) {
|
|
325302
326108
|
const { theme, width: width2, height: height2, obsType, featureType, obsSetsColumnNameMappingReversed, sampleSetsColumnNameMappingReversed, sampleSetSelection, obsSetSelection, obsSetColor, sampleSetColor, data: data2, marginTop = 5, marginRight = 5, marginLeft = 50, marginBottom = 50, onFeatureClick, featurePointSignificanceThreshold, featurePointFoldChangeThreshold, featureLabelSignificanceThreshold, featureLabelFoldChangeThreshold } = props;
|
|
325303
326109
|
const svgRef = useRef();
|
|
@@ -325359,10 +326165,10 @@ function VolcanoPlot(props) {
|
|
|
325359
326165
|
const obsSetPath2 = [...rawObsSetPath];
|
|
325360
326166
|
obsSetPath2[0] = obsSetsColumnNameMappingReversed[rawObsSetPath[0]];
|
|
325361
326167
|
const color2 = obsSetColorScale(obsSetPath2);
|
|
325362
|
-
obsSetG.append("g").selectAll("circle").data(filteredDf).join("circle").attr("cx", (d) => xScale(d.logFoldChange)).attr("cy", (d) => yScale(d.minusLog10p)).attr("r", 3).attr("opacity", 0.5).attr("fill", color2).on("click", (event2, d) => {
|
|
326168
|
+
obsSetG.append("g").selectAll("circle").data(filteredDf).join("circle").attr("cx", (d) => xScale(d.logFoldChange)).attr("cy", (d, i2) => yScale(d.minusLog10p) + (!Number.isFinite(d.minusLog10p) ? topJitter(i2, 20) : 0)).attr("r", 3).attr("opacity", 0.5).attr("fill", color2).on("click", (event2, d) => {
|
|
325363
326169
|
onFeatureClick(d.featureId);
|
|
325364
326170
|
});
|
|
325365
|
-
const textElements = obsSetG.append("g").selectAll("text").data(filteredDf).join("text").text((d) => d.featureId).attr("text-anchor", (d) => d.logFoldChange < 0 ? "end" : "start").attr("x", (d) => xScale(d.logFoldChange)).attr("y", (d) => yScale(d.minusLog10p)).style("display", (d) => Math.abs(d.logFoldChange) < (featureLabelFoldChangeThreshold ?? 5) || d.featureSignificance >= (featureLabelSignificanceThreshold ?? 0.01) ? "none" : void 0).attr("fill", color2).on("click", (event2, d) => {
|
|
326171
|
+
const textElements = obsSetG.append("g").selectAll("text").data(filteredDf).join("text").text((d) => d.featureId).attr("text-anchor", (d) => d.logFoldChange < 0 ? "end" : "start").attr("x", (d) => xScale(d.logFoldChange)).attr("y", (d, i2) => yScale(d.minusLog10p) + (!Number.isFinite(d.minusLog10p) ? topJitter(i2, 20) : 0)).style("display", (d) => Math.abs(d.logFoldChange) < (featureLabelFoldChangeThreshold ?? 5) || d.featureSignificance >= (featureLabelSignificanceThreshold ?? 0.01) ? "none" : void 0).attr("fill", color2).on("click", (event2, d) => {
|
|
325366
326172
|
onFeatureClick(d.featureId);
|
|
325367
326173
|
});
|
|
325368
326174
|
textElements.append("title").text((d) => `${featureType}: ${d.featureId}
|
|
@@ -349423,6 +350229,7 @@ const baseCoordinationTypes = [
|
|
|
349423
350229
|
new PluginCoordinationType(CoordinationType$1.SPATIAL_CHANNEL_LABELS_VISIBLE, true, z.boolean()),
|
|
349424
350230
|
new PluginCoordinationType(CoordinationType$1.SPATIAL_CHANNEL_LABELS_ORIENTATION, "vertical", z.enum(["vertical", "horizontal"])),
|
|
349425
350231
|
new PluginCoordinationType(CoordinationType$1.SPATIAL_CHANNEL_LABEL_SIZE, 14, z.number()),
|
|
350232
|
+
new PluginCoordinationType(CoordinationType$1.SPATIAL_CHANNELS_SORT_ORDER, "original", z.enum(["original", "alphabetical"])),
|
|
349426
350233
|
new PluginCoordinationType(CoordinationType$1.SAMPLE_TYPE, "sample", z.string().nullable()),
|
|
349427
350234
|
// TODO: remove one array level and use multi-coordination for sampleSetSelection?
|
|
349428
350235
|
new PluginCoordinationType(CoordinationType$1.SAMPLE_FILTER, null, z.array(z.string()).nullable()),
|
|
@@ -349522,7 +350329,7 @@ function Vitessce(props) {
|
|
|
349522
350329
|
);
|
|
349523
350330
|
}
|
|
349524
350331
|
export {
|
|
349525
|
-
|
|
350332
|
+
GREY_HEX as $,
|
|
349526
350333
|
require_descriptors as A,
|
|
349527
350334
|
BaseDecoder as B,
|
|
349528
350335
|
CoordinationType$1 as C,
|
|
@@ -349551,13 +350358,14 @@ export {
|
|
|
349551
350358
|
require_redefine as Z,
|
|
349552
350359
|
require_objectAssign as _,
|
|
349553
350360
|
getDefaultExportFromCjs$1 as a,
|
|
349554
|
-
|
|
349555
|
-
|
|
349556
|
-
|
|
349557
|
-
|
|
349558
|
-
|
|
349559
|
-
|
|
349560
|
-
|
|
350361
|
+
diffCameraState as a0,
|
|
350362
|
+
Vitessce as a1,
|
|
350363
|
+
PluginFileType as a2,
|
|
350364
|
+
PluginViewType as a3,
|
|
350365
|
+
PluginCoordinationType as a4,
|
|
350366
|
+
PluginJointFileType as a5,
|
|
350367
|
+
PluginAsyncFunction as a6,
|
|
350368
|
+
z as a7,
|
|
349561
350369
|
LercAddCompression as b,
|
|
349562
350370
|
commonjsGlobal$1 as c,
|
|
349563
350371
|
requireAssign as d,
|