@vitessce/launcher 4.0.1 → 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-BTEzmbOK.js → GeometryAndMeshXR-DsObDSMF.js} +1 -1
- package/dist/{ReactNeuroglancer-Bw5gQWL3.js → ReactNeuroglancer-C2C-vEVu.js} +169 -57
- package/dist/{XREnterButton-Cy5hojS1.js → XREnterButton-B6j_tE1d.js} +1 -1
- package/dist/{XRSceneComponents-BTW4vULD.js → XRSceneComponents-BgZ4J_JS.js} +1 -1
- package/dist/{XRWrapper-BFmCjZo_.js → XRWrapper-BLKqjWwm.js} +2 -2
- package/dist/{deflate-Bbx7Vqb7.js → deflate-38TS7div.js} +1 -1
- package/dist/{higlass-C6IxqTVD.js → higlass-CKuPDg4y.js} +1 -1
- package/dist/{index-BlOIc49f.js → index-CA6Y_Dls.js} +5 -5
- package/dist/{index-DYR0bplz.js → index-D-cJewP-.js} +966 -184
- package/dist/{index-BSOXpbtb.js → index-gStG4FEQ.js} +1 -1
- package/dist/index.js +3 -3
- package/dist/{jpeg-Co4ZcifY.js → jpeg-BGB-_EKG.js} +1 -1
- package/dist/{lerc-_s2Wotdl.js → lerc-Db0ZEZ3c.js} +1 -1
- package/dist/{lzw-CKCb2yMZ.js → lzw-BmHVONBc.js} +1 -1
- package/dist/{packbits-BNHyrTcI.js → packbits-DKF2IGBX.js} +1 -1
- package/dist/{raw-CCLdztVu.js → raw-DMNeLVd7.js} +1 -1
- package/dist/{webimage-BozDrenu.js → webimage-BTp31_-j.js} +1 -1
- package/dist/{xrStore-D3LG-myx.js → xrStore-CDyKy5UF.js} +1 -1
- package/package.json +9 -9
|
@@ -6375,12 +6375,12 @@ function baseIsEqual$3(value2, other, bitmask, customizer, stack2) {
|
|
|
6375
6375
|
var now$4 = function() {
|
|
6376
6376
|
return root$d.Date.now();
|
|
6377
6377
|
};
|
|
6378
|
-
var FUNC_ERROR_TEXT$
|
|
6378
|
+
var FUNC_ERROR_TEXT$3 = "Expected a function";
|
|
6379
6379
|
var nativeMax$3 = Math.max, nativeMin$1 = Math.min;
|
|
6380
6380
|
function debounce$5(func, wait2, options) {
|
|
6381
6381
|
var lastArgs, lastThis, maxWait, result, timerId, lastCallTime, lastInvokeTime = 0, leading = false, maxing = false, trailing = true;
|
|
6382
6382
|
if (typeof func != "function") {
|
|
6383
|
-
throw new TypeError(FUNC_ERROR_TEXT$
|
|
6383
|
+
throw new TypeError(FUNC_ERROR_TEXT$3);
|
|
6384
6384
|
}
|
|
6385
6385
|
wait2 = toNumber$3(wait2) || 0;
|
|
6386
6386
|
if (isObject$f(options)) {
|
|
@@ -6538,6 +6538,22 @@ var range$e = createRange();
|
|
|
6538
6538
|
function sum$6(array2) {
|
|
6539
6539
|
return array2 && array2.length ? baseSum(array2, identity$h) : 0;
|
|
6540
6540
|
}
|
|
6541
|
+
var FUNC_ERROR_TEXT$2 = "Expected a function";
|
|
6542
|
+
function throttle$1(func, wait2, options) {
|
|
6543
|
+
var leading = true, trailing = true;
|
|
6544
|
+
if (typeof func != "function") {
|
|
6545
|
+
throw new TypeError(FUNC_ERROR_TEXT$2);
|
|
6546
|
+
}
|
|
6547
|
+
if (isObject$f(options)) {
|
|
6548
|
+
leading = "leading" in options ? !!options.leading : leading;
|
|
6549
|
+
trailing = "trailing" in options ? !!options.trailing : trailing;
|
|
6550
|
+
}
|
|
6551
|
+
return debounce$5(func, wait2, {
|
|
6552
|
+
"leading": leading,
|
|
6553
|
+
"maxWait": wait2,
|
|
6554
|
+
"trailing": trailing
|
|
6555
|
+
});
|
|
6556
|
+
}
|
|
6541
6557
|
var INFINITY = 1 / 0;
|
|
6542
6558
|
var createSet = !(Set$3 && 1 / setToArray$2(new Set$3([, -0]))[1] == INFINITY) ? noop$h : function(values3) {
|
|
6543
6559
|
return new Set$3(values3);
|
|
@@ -11882,7 +11898,18 @@ const ngPrecomputedMeshSchema = z.object({
|
|
|
11882
11898
|
const ngPointAnnotationSchema = z.object({
|
|
11883
11899
|
projectionAnnotationSpacing: z.number(),
|
|
11884
11900
|
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."),
|
|
11885
|
-
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.")
|
|
11901
|
+
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."),
|
|
11902
|
+
transform: z.object({
|
|
11903
|
+
matrix: z.array(z.array(z.number())),
|
|
11904
|
+
outputDimensions: z.record(z.tuple([z.number(), z.string()]))
|
|
11905
|
+
}).optional().describe("A coordinate transformation matrix to apply to the annotation layer source to map annotation coordinates to the global coordinate space."),
|
|
11906
|
+
// Note: See comments in neuroglancer-sorger.js
|
|
11907
|
+
// We may remove these in the future, pending clarification
|
|
11908
|
+
// to questions in the tissue-map-tools repo
|
|
11909
|
+
// - https://github.com/hms-dbmi/tissue-map-tools/issues/20
|
|
11910
|
+
// - https://github.com/hms-dbmi/tissue-map-tools/issues/38
|
|
11911
|
+
quantitativeColorProp: z.string().optional(),
|
|
11912
|
+
quantitativeColorMax: z.number().optional()
|
|
11886
11913
|
}).partial().nullable();
|
|
11887
11914
|
const obsEmbeddingAnndataSchema = annDataObsEmbedding;
|
|
11888
11915
|
const obsSpotsAnndataSchema = annDataObsLocations;
|
|
@@ -19295,7 +19322,7 @@ const { tss } = createTss({
|
|
|
19295
19322
|
},
|
|
19296
19323
|
"usePlugin": useMuiThemeStyleOverridesPlugin
|
|
19297
19324
|
});
|
|
19298
|
-
const useStyles$
|
|
19325
|
+
const useStyles$z = tss.create({});
|
|
19299
19326
|
function createChainedFunction$1(...funcs) {
|
|
19300
19327
|
return funcs.reduce((acc, func) => {
|
|
19301
19328
|
if (func == null) {
|
|
@@ -74105,7 +74132,7 @@ const Popper = React.forwardRef((props, ref2) => {
|
|
|
74105
74132
|
}, [handlePopperRef]);
|
|
74106
74133
|
React.useImperativeHandle(popperRefProp, () => popperRef.current, []);
|
|
74107
74134
|
const [exited, setExited] = React.useState(true);
|
|
74108
|
-
const { theme } = useStyles$
|
|
74135
|
+
const { theme } = useStyles$z();
|
|
74109
74136
|
const rtlPlacement = flipPlacement(initialPlacement, theme);
|
|
74110
74137
|
const [placement, setPlacement] = React.useState(rtlPlacement);
|
|
74111
74138
|
React.useEffect(() => {
|
|
@@ -74839,7 +74866,7 @@ var VariableSizeList$1 = /* @__PURE__ */ createListComponent({
|
|
|
74839
74866
|
});
|
|
74840
74867
|
const VariableSizeList = VariableSizeList$1;
|
|
74841
74868
|
const LIST_ROW_HEIGHT$1 = 48;
|
|
74842
|
-
const useStyles$
|
|
74869
|
+
const useStyles$y = makeStyles()(() => ({
|
|
74843
74870
|
searchInput: {
|
|
74844
74871
|
lineHeight: "initial",
|
|
74845
74872
|
height: "auto !important"
|
|
@@ -74879,7 +74906,7 @@ const ListboxComponent$1 = React__default.forwardRef((props, ref2) => {
|
|
|
74879
74906
|
});
|
|
74880
74907
|
function SimpleAutocomplete(props) {
|
|
74881
74908
|
const { getMatches, onChange, textInputLabel = "Enter a gene", getItemLabel = (option) => option.label } = props;
|
|
74882
|
-
const { classes: classes2 } = useStyles$
|
|
74909
|
+
const { classes: classes2 } = useStyles$y();
|
|
74883
74910
|
const [potentialItems, setPotentialItems] = useState([]);
|
|
74884
74911
|
const handleInputChange = async (_event, value2) => {
|
|
74885
74912
|
if (!value2) {
|
|
@@ -84429,7 +84456,7 @@ function defaultUrlTransform(value2) {
|
|
|
84429
84456
|
}
|
|
84430
84457
|
return "";
|
|
84431
84458
|
}
|
|
84432
|
-
const useStyles$
|
|
84459
|
+
const useStyles$x = makeStyles()((theme) => ({
|
|
84433
84460
|
description: {
|
|
84434
84461
|
"& p, details, table": {
|
|
84435
84462
|
fontSize: "80%",
|
|
@@ -84466,7 +84493,7 @@ const useStyles$w = makeStyles()((theme) => ({
|
|
|
84466
84493
|
}));
|
|
84467
84494
|
function Description(props) {
|
|
84468
84495
|
const { description: description2, metadata: metadata2, descriptionType } = props;
|
|
84469
|
-
const { classes: classes2 } = useStyles$
|
|
84496
|
+
const { classes: classes2 } = useStyles$x();
|
|
84470
84497
|
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)] });
|
|
84471
84498
|
}
|
|
84472
84499
|
function DescriptionSubscriber(props) {
|
|
@@ -92718,6 +92745,37 @@ function dataToCellSetsTree(data2, options) {
|
|
|
92718
92745
|
return cellSetsTree;
|
|
92719
92746
|
}
|
|
92720
92747
|
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]];
|
|
92748
|
+
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]];
|
|
92749
|
+
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]];
|
|
92750
|
+
const schemeJet = Array.from({ length: 256 }, (_, i2) => {
|
|
92751
|
+
const t4 = i2 / 255;
|
|
92752
|
+
let r3;
|
|
92753
|
+
let g2;
|
|
92754
|
+
let b2;
|
|
92755
|
+
if (t4 < 0.125) {
|
|
92756
|
+
r3 = 0;
|
|
92757
|
+
g2 = 0;
|
|
92758
|
+
b2 = 0.5 + t4 * 4;
|
|
92759
|
+
} else if (t4 < 0.375) {
|
|
92760
|
+
r3 = 0;
|
|
92761
|
+
g2 = (t4 - 0.125) * 4;
|
|
92762
|
+
b2 = 1;
|
|
92763
|
+
} else if (t4 < 0.625) {
|
|
92764
|
+
r3 = (t4 - 0.375) * 4;
|
|
92765
|
+
g2 = 1;
|
|
92766
|
+
b2 = 1 - (t4 - 0.375) * 4;
|
|
92767
|
+
} else if (t4 < 0.875) {
|
|
92768
|
+
r3 = 1;
|
|
92769
|
+
g2 = 1 - (t4 - 0.625) * 4;
|
|
92770
|
+
b2 = 0;
|
|
92771
|
+
} else {
|
|
92772
|
+
r3 = 1 - (t4 - 0.875) * 4;
|
|
92773
|
+
g2 = 0;
|
|
92774
|
+
b2 = 0;
|
|
92775
|
+
}
|
|
92776
|
+
return [Math.round(r3 * 255), Math.round(g2 * 255), Math.round(b2 * 255)];
|
|
92777
|
+
});
|
|
92778
|
+
const schemeGreys = Array.from({ length: 256 }, (_, i2) => [i2, i2, i2]);
|
|
92721
92779
|
function rgbSpline$1(spline) {
|
|
92722
92780
|
return (colors2) => {
|
|
92723
92781
|
const n3 = colors2.length;
|
|
@@ -92755,7 +92813,15 @@ function basis$2(values3) {
|
|
|
92755
92813
|
};
|
|
92756
92814
|
}
|
|
92757
92815
|
const interpolateRgbBasis = rgbSpline$1(basis$2);
|
|
92816
|
+
function interpolateSequentialMulti(range2) {
|
|
92817
|
+
const n3 = range2.length;
|
|
92818
|
+
return (t4) => range2[Math.max(0, Math.min(n3 - 1, Math.floor(t4 * n3)))];
|
|
92819
|
+
}
|
|
92758
92820
|
interpolateRgbBasis(schemeRdBu);
|
|
92821
|
+
const interpolatePlasma = interpolateSequentialMulti(schemePlasma);
|
|
92822
|
+
const interpolateViridis = interpolateSequentialMulti(schemeViridis);
|
|
92823
|
+
const interpolateJet = interpolateSequentialMulti(schemeJet);
|
|
92824
|
+
const interpolateGreys = interpolateSequentialMulti(schemeGreys);
|
|
92759
92825
|
function getCellColors(params2) {
|
|
92760
92826
|
const { cellSets, cellSetSelection, cellSetColor, obsIndex, theme } = params2;
|
|
92761
92827
|
if (cellSetSelection && cellSets) {
|
|
@@ -99537,7 +99603,7 @@ const Tooltip$2 = /* @__PURE__ */ React.forwardRef((props, ref2) => {
|
|
|
99537
99603
|
}, extraProps), getChildren());
|
|
99538
99604
|
});
|
|
99539
99605
|
const nodeHeight = 32;
|
|
99540
|
-
const useStyles$
|
|
99606
|
+
const useStyles$w = makeStyles()((theme) => ({
|
|
99541
99607
|
setsManager: {
|
|
99542
99608
|
position: "relative",
|
|
99543
99609
|
width: "100%",
|
|
@@ -99704,7 +99770,7 @@ const useStyles$v = makeStyles()((theme) => ({
|
|
|
99704
99770
|
}));
|
|
99705
99771
|
function SetsManagerTreeGlobalStyles(props) {
|
|
99706
99772
|
const { classes: classes2 } = props;
|
|
99707
|
-
const { theme } = useStyles$
|
|
99773
|
+
const { theme } = useStyles$z();
|
|
99708
99774
|
return jsx$1(ScopedGlobalStyles, { parentClassName: classes2.setsManagerTree, styles: {
|
|
99709
99775
|
".rc-tree": {
|
|
99710
99776
|
paddingLeft: "0",
|
|
@@ -100045,7 +100111,7 @@ function HelpTooltipGlobalStyles(props) {
|
|
|
100045
100111
|
}
|
|
100046
100112
|
function PopoverGlobalStyles(props) {
|
|
100047
100113
|
const { classes: classes2 } = props;
|
|
100048
|
-
const { theme } = useStyles$
|
|
100114
|
+
const { theme } = useStyles$z();
|
|
100049
100115
|
return jsx$1(ScopedGlobalStyles, { parentClassName: classes2.popover, styles: {
|
|
100050
100116
|
".rc-tooltip-inner": {
|
|
100051
100117
|
boxSizing: "border-box",
|
|
@@ -104729,7 +104795,7 @@ function NamedSetNodeStatic(props) {
|
|
|
104729
104795
|
const onClick = level === 0 && !expanded ? () => onCheckLevel(nodeKey, nextLevelToCheck) : () => onNodeView(path2);
|
|
104730
104796
|
const tooltipProps = disableTooltip ? { visible: false } : {};
|
|
104731
104797
|
const popoverMenuConfig = makeNodeViewMenuConfig(props);
|
|
104732
|
-
const { classes: classes2 } = useStyles$
|
|
104798
|
+
const { classes: classes2 } = useStyles$w();
|
|
104733
104799
|
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 })] });
|
|
104734
104800
|
}
|
|
104735
104801
|
function NamedSetNodeEditing(props) {
|
|
@@ -104741,7 +104807,7 @@ function NamedSetNodeEditing(props) {
|
|
|
104741
104807
|
onNodeSetName(path2, currentTitle, true);
|
|
104742
104808
|
}
|
|
104743
104809
|
}
|
|
104744
|
-
const { classes: classes2 } = useStyles$
|
|
104810
|
+
const { classes: classes2 } = useStyles$w();
|
|
104745
104811
|
return jsxs("span", { className: classes2.titleButtonWithInput, children: [jsx$1("input", {
|
|
104746
104812
|
// eslint-disable-next-line jsx-a11y/no-autofocus
|
|
104747
104813
|
autoFocus: true,
|
|
@@ -104767,7 +104833,7 @@ function LevelsButtons(props) {
|
|
|
104767
104833
|
onCheckLevel(nodeKey, newLevel);
|
|
104768
104834
|
}
|
|
104769
104835
|
}
|
|
104770
|
-
const { classes: classes2 } = useStyles$
|
|
104836
|
+
const { classes: classes2 } = useStyles$w();
|
|
104771
104837
|
return jsx$1("div", { className: classes2.levelButtonsContainer, children: range$e(1, height2 + 1).map((i2) => {
|
|
104772
104838
|
const isChecked = isEqual$3(path2, checkedLevelPath) && i2 === checkedLevelIndex;
|
|
104773
104839
|
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);
|
|
@@ -104851,7 +104917,7 @@ let TreeNode$1 = class TreeNode extends TreeNode$2 {
|
|
|
104851
104917
|
};
|
|
104852
104918
|
function PlusButton(props) {
|
|
104853
104919
|
const { datatype, onError, onImportTree, onCreateLevelZeroNode, importable, editable } = props;
|
|
104854
|
-
const { classes: classes2 } = useStyles$
|
|
104920
|
+
const { classes: classes2 } = useStyles$w();
|
|
104855
104921
|
const onImport = useCallback((importHandler, mimeType) => () => {
|
|
104856
104922
|
const uploadInputNode = document.createElement("input");
|
|
104857
104923
|
uploadInputNode.setAttribute("type", "file");
|
|
@@ -104968,7 +105034,7 @@ function SetsManager(props) {
|
|
|
104968
105034
|
}, onNodeCheckNewName, onNodeSetIsEditing: setIsEditingNodeName, onNodeRemove, onExportLevelZeroNodeJSON, onExportLevelZeroNodeTabular, onExportSetJSON, disableTooltip: isDragging, onDragStart: () => setIsDragging(true), onDragEnd: () => setIsDragging(false), children: renderTreeNodes(node2.children, readOnly, newPath) }, pathToKey(newPath));
|
|
104969
105035
|
});
|
|
104970
105036
|
}
|
|
104971
|
-
const { classes: classes2 } = useStyles$
|
|
105037
|
+
const { classes: classes2 } = useStyles$w();
|
|
104972
105038
|
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) => {
|
|
104973
105039
|
const { eventKey: dropKey } = info2.node.props;
|
|
104974
105040
|
const { eventKey: dragKey } = info2.dragNode.props;
|
|
@@ -210933,22 +210999,22 @@ async function getDecoder(fileDirectory) {
|
|
|
210933
210999
|
const Decoder = await importFn();
|
|
210934
211000
|
return new Decoder(fileDirectory);
|
|
210935
211001
|
}
|
|
210936
|
-
addDecoder([void 0, 1], () => import("./raw-
|
|
210937
|
-
addDecoder(5, () => import("./lzw-
|
|
211002
|
+
addDecoder([void 0, 1], () => import("./raw-DMNeLVd7.js").then((m2) => m2.default));
|
|
211003
|
+
addDecoder(5, () => import("./lzw-BmHVONBc.js").then((m2) => m2.default));
|
|
210938
211004
|
addDecoder(6, () => {
|
|
210939
211005
|
throw new Error("old style JPEG compression is not supported.");
|
|
210940
211006
|
});
|
|
210941
|
-
addDecoder(7, () => import("./jpeg-
|
|
210942
|
-
addDecoder([8, 32946], () => import("./deflate-
|
|
210943
|
-
addDecoder(32773, () => import("./packbits-
|
|
211007
|
+
addDecoder(7, () => import("./jpeg-BGB-_EKG.js").then((m2) => m2.default));
|
|
211008
|
+
addDecoder([8, 32946], () => import("./deflate-38TS7div.js").then((m2) => m2.default));
|
|
211009
|
+
addDecoder(32773, () => import("./packbits-DKF2IGBX.js").then((m2) => m2.default));
|
|
210944
211010
|
addDecoder(
|
|
210945
211011
|
34887,
|
|
210946
|
-
() => import("./lerc-
|
|
211012
|
+
() => import("./lerc-Db0ZEZ3c.js").then(async (m2) => {
|
|
210947
211013
|
await m2.zstd.init();
|
|
210948
211014
|
return m2;
|
|
210949
211015
|
}).then((m2) => m2.default)
|
|
210950
211016
|
);
|
|
210951
|
-
addDecoder(50001, () => import("./webimage-
|
|
211017
|
+
addDecoder(50001, () => import("./webimage-BTp31_-j.js").then((m2) => m2.default));
|
|
210952
211018
|
function copyNewSize(array2, width2, height2, samplesPerPixel = 1) {
|
|
210953
211019
|
return new (Object.getPrototypeOf(array2)).constructor(width2 * height2 * samplesPerPixel);
|
|
210954
211020
|
}
|
|
@@ -227722,7 +227788,7 @@ class ContourLayerWithText extends ContourLayer {
|
|
|
227722
227788
|
}
|
|
227723
227789
|
ContourLayerWithText.layerName = "ContourLayerWithText";
|
|
227724
227790
|
ContourLayerWithText.defaultProps = defaultProps;
|
|
227725
|
-
const useStyles$
|
|
227791
|
+
const useStyles$v = makeStyles()(() => ({
|
|
227726
227792
|
toolButton: {
|
|
227727
227793
|
display: "inline-flex",
|
|
227728
227794
|
"&:active": {
|
|
@@ -227784,12 +227850,12 @@ const useStyles$u = makeStyles()(() => ({
|
|
|
227784
227850
|
}));
|
|
227785
227851
|
function IconTool(props) {
|
|
227786
227852
|
const { alt, onClick, isActive: isActive2, children: children3 } = props;
|
|
227787
|
-
const { classes: classes2 } = useStyles$
|
|
227853
|
+
const { classes: classes2 } = useStyles$v();
|
|
227788
227854
|
return jsx$1("button", { className: clsx(classes2.toolIcon, { [classes2.toolActive]: isActive2 }), onClick, type: "button", title: alt, children: children3 });
|
|
227789
227855
|
}
|
|
227790
227856
|
function IconButton(props) {
|
|
227791
227857
|
const { alt, onClick, children: children3 } = props;
|
|
227792
|
-
const { classes: classes2 } = useStyles$
|
|
227858
|
+
const { classes: classes2 } = useStyles$v();
|
|
227793
227859
|
return jsx$1("button", { className: clsx(classes2.toolIcon, classes2.toolButton), onClick, type: "button", title: alt, children: children3 });
|
|
227794
227860
|
}
|
|
227795
227861
|
function ToolMenu(props) {
|
|
@@ -227797,7 +227863,7 @@ function ToolMenu(props) {
|
|
|
227797
227863
|
const lassoIconAltText = "Select lasso";
|
|
227798
227864
|
const { setActiveTool, activeTool, visibleTools = { pan: true, selectLasso: true, recenter: true }, recenterOnClick = () => {
|
|
227799
227865
|
} } = props;
|
|
227800
|
-
const { classes: classes2 } = useStyles$
|
|
227866
|
+
const { classes: classes2 } = useStyles$v();
|
|
227801
227867
|
const onRecenterButtonCLick = () => {
|
|
227802
227868
|
recenterOnClick();
|
|
227803
227869
|
};
|
|
@@ -228954,7 +229020,7 @@ function ScatterplotOptions(props) {
|
|
|
228954
229020
|
id: `feature-aggregation-strategy-${scatterplotOptionsId}`
|
|
228955
229021
|
}, children: FEATURE_AGGREGATION_STRATEGIES$2.map((opt) => jsx$1("option", { value: opt, children: capitalize$3(opt) }, opt)) }) })] }) : null] });
|
|
228956
229022
|
}
|
|
228957
|
-
const useStyles$
|
|
229023
|
+
const useStyles$u = makeStyles()((theme) => ({
|
|
228958
229024
|
tooltipAnchor: {
|
|
228959
229025
|
position: "relative",
|
|
228960
229026
|
width: "0px",
|
|
@@ -228985,7 +229051,7 @@ const useStyles$t = makeStyles()((theme) => ({
|
|
|
228985
229051
|
function Tooltip3(props) {
|
|
228986
229052
|
const { x: x2, y: y2, parentWidth, parentHeight, children: children3 } = props;
|
|
228987
229053
|
const ref2 = useRef();
|
|
228988
|
-
const { classes: classes2 } = useStyles$
|
|
229054
|
+
const { classes: classes2 } = useStyles$u();
|
|
228989
229055
|
const [placementX, setPlacementX] = useState("start");
|
|
228990
229056
|
const [placementY, setPlacementY] = useState("bottom");
|
|
228991
229057
|
const getTooltipContainer = useVitessceContainer(ref2);
|
|
@@ -229001,7 +229067,7 @@ function Tooltip3(props) {
|
|
|
229001
229067
|
}, [x2, y2, parentWidth, parentHeight]);
|
|
229002
229068
|
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 });
|
|
229003
229069
|
}
|
|
229004
|
-
const useStyles$
|
|
229070
|
+
const useStyles$t = makeStyles()((theme) => ({
|
|
229005
229071
|
cellEmphasisCrosshair: {
|
|
229006
229072
|
zIndex: 50,
|
|
229007
229073
|
position: "absolute",
|
|
@@ -229012,7 +229078,7 @@ const useStyles$s = makeStyles()((theme) => ({
|
|
|
229012
229078
|
}));
|
|
229013
229079
|
function Tooltip2D(props) {
|
|
229014
229080
|
const { parentUuid, sourceUuid, x: x2, y: y2, parentWidth, parentHeight, children: children3 } = props;
|
|
229015
|
-
const { classes: classes2 } = useStyles$
|
|
229081
|
+
const { classes: classes2 } = useStyles$t();
|
|
229016
229082
|
if (x2 < 0 || x2 > parentWidth || y2 < 0 || y2 > parentHeight) {
|
|
229017
229083
|
return null;
|
|
229018
229084
|
}
|
|
@@ -232924,7 +232990,7 @@ function getXlinkHref(cmap) {
|
|
|
232924
232990
|
const xlinkHref = ramp(color2.copy().domain(quantize$3(interpolate$1$1(0, 1), n3))).toDataURL();
|
|
232925
232991
|
return xlinkHref;
|
|
232926
232992
|
}
|
|
232927
|
-
const useStyles$
|
|
232993
|
+
const useStyles$s = makeStyles()(() => ({
|
|
232928
232994
|
legend: {
|
|
232929
232995
|
position: "relative",
|
|
232930
232996
|
// Needed for absolute positioning of slider overlay
|
|
@@ -233121,7 +233187,7 @@ function Legend(props) {
|
|
|
233121
233187
|
contourThresholds
|
|
233122
233188
|
} = props;
|
|
233123
233189
|
const svgRef = useRef(null);
|
|
233124
|
-
const { classes: classes2 } = useStyles$
|
|
233190
|
+
const { classes: classes2 } = useStyles$s();
|
|
233125
233191
|
const [localRange, setLocalRange] = useState(featureValueColormapRange);
|
|
233126
233192
|
useEffect(() => {
|
|
233127
233193
|
setLocalRange(featureValueColormapRange);
|
|
@@ -233455,7 +233521,7 @@ function Legend(props) {
|
|
|
233455
233521
|
}
|
|
233456
233522
|
} })] })] });
|
|
233457
233523
|
}
|
|
233458
|
-
const useStyles$
|
|
233524
|
+
const useStyles$r = makeStyles()(() => ({
|
|
233459
233525
|
multiLegend: {
|
|
233460
233526
|
position: "absolute",
|
|
233461
233527
|
top: "0px",
|
|
@@ -233482,7 +233548,7 @@ function MultiLegend(props) {
|
|
|
233482
233548
|
pointLayerCoordination,
|
|
233483
233549
|
pointMultiIndicesData
|
|
233484
233550
|
} = props;
|
|
233485
|
-
const { classes: classes2 } = useStyles$
|
|
233551
|
+
const { classes: classes2 } = useStyles$r();
|
|
233486
233552
|
const reversedSegmentationLayerScopes = useMemo$1(() => [...segmentationLayerScopes || []].reverse(), [segmentationLayerScopes]);
|
|
233487
233553
|
const reversedSpotLayerScopes = useMemo$1(() => [...spotLayerScopes || []].reverse(), [spotLayerScopes]);
|
|
233488
233554
|
const reversedPointLayerScopes = useMemo$1(() => [...pointLayerScopes || []].reverse(), [pointLayerScopes]);
|
|
@@ -233575,7 +233641,7 @@ function MultiLegend(props) {
|
|
|
233575
233641
|
}) : null;
|
|
233576
233642
|
}) : null] });
|
|
233577
233643
|
}
|
|
233578
|
-
const useStyles$
|
|
233644
|
+
const useStyles$q = makeStyles()(() => ({
|
|
233579
233645
|
channelNamesLegendContainer: {
|
|
233580
233646
|
position: "absolute",
|
|
233581
233647
|
bottom: "0px",
|
|
@@ -233598,7 +233664,7 @@ const useStyles$p = makeStyles()(() => ({
|
|
|
233598
233664
|
}));
|
|
233599
233665
|
function ChannelNamesLegend(props) {
|
|
233600
233666
|
const { images, imageLayerScopes, imageLayerCoordination, imageChannelScopesByLayer, imageChannelCoordination } = props;
|
|
233601
|
-
const { classes: classes2 } = useStyles$
|
|
233667
|
+
const { classes: classes2 } = useStyles$q();
|
|
233602
233668
|
const reversedImageLayerScopes = useMemo$1(() => [...imageLayerScopes || []].reverse(), [imageLayerScopes]);
|
|
233603
233669
|
return jsx$1("div", { className: classes2.channelNamesLegendContainer, children: imageLayerScopes ? reversedImageLayerScopes.map((layerScope) => {
|
|
233604
233670
|
const layerCoordination = imageLayerCoordination[0][layerScope];
|
|
@@ -255205,7 +255271,7 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
|
|
|
255205
255271
|
this.viewInfoDidUpdate();
|
|
255206
255272
|
const shallowDiff2 = (propName) => prevProps[propName] !== this.props[propName];
|
|
255207
255273
|
const shallowDiffByLayer2 = (propName, scopeName) => prevProps?.[propName]?.[scopeName] !== this.props?.[propName]?.[scopeName];
|
|
255208
|
-
const
|
|
255274
|
+
const shallowDiffByChannel2 = (propName, firstName, secondName) => prevProps?.[propName]?.[firstName]?.[secondName] !== this.props?.[propName]?.[firstName]?.[secondName];
|
|
255209
255275
|
const shallowDiffByLayerCoordination = (propName, layerScope) => prevProps?.[propName]?.[0]?.[layerScope] !== this.props?.[propName]?.[0]?.[layerScope];
|
|
255210
255276
|
const shallowDiffByChannelCoordination = (propName, layerScope, channelScope) => prevProps?.[propName]?.[0]?.[layerScope]?.[channelScope] !== this.props?.[propName]?.[0]?.[layerScope]?.[channelScope];
|
|
255211
255277
|
let forceUpdate = false;
|
|
@@ -255226,7 +255292,7 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
|
|
|
255226
255292
|
} else {
|
|
255227
255293
|
this.props.segmentationLayerScopes?.forEach((layerScope) => {
|
|
255228
255294
|
this.props.segmentationChannelScopesByLayer?.[layerScope]?.forEach((channelScope) => {
|
|
255229
|
-
if (
|
|
255295
|
+
if (shallowDiffByChannel2("obsSegmentationsLocations", layerScope, channelScope)) {
|
|
255230
255296
|
this.onUpdateSegmentationsLocationsData(layerScope, channelScope);
|
|
255231
255297
|
forceUpdate = true;
|
|
255232
255298
|
}
|
|
@@ -255239,7 +255305,7 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
|
|
|
255239
255305
|
} else {
|
|
255240
255306
|
this.props.segmentationLayerScopes?.forEach((layerScope) => {
|
|
255241
255307
|
this.props.segmentationChannelScopesByLayer?.[layerScope]?.forEach((channelScope) => {
|
|
255242
|
-
if (
|
|
255308
|
+
if (shallowDiffByChannel2("obsSegmentationsSets", layerScope, channelScope) || shallowDiffByChannelCoordination("segmentationChannelCoordination", layerScope, channelScope)) {
|
|
255243
255309
|
this.onUpdateSegmentationsSetsData(layerScope, channelScope);
|
|
255244
255310
|
forceUpdate = true;
|
|
255245
255311
|
}
|
|
@@ -255252,7 +255318,7 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
|
|
|
255252
255318
|
} else {
|
|
255253
255319
|
this.props.segmentationLayerScopes?.forEach((layerScope) => {
|
|
255254
255320
|
this.props.segmentationChannelScopesByLayer?.[layerScope]?.forEach((channelScope) => {
|
|
255255
|
-
if (
|
|
255321
|
+
if (shallowDiffByChannel2("segmentationMatrixIndices", layerScope, channelScope)) {
|
|
255256
255322
|
this.onUpdateSegmentationsIndexData(layerScope, channelScope);
|
|
255257
255323
|
forceUpdate = true;
|
|
255258
255324
|
}
|
|
@@ -255265,7 +255331,7 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
|
|
|
255265
255331
|
} else {
|
|
255266
255332
|
this.props.segmentationLayerScopes.forEach((layerScope) => {
|
|
255267
255333
|
this.props.segmentationChannelScopesByLayer?.[layerScope]?.forEach((channelScope) => {
|
|
255268
|
-
if (
|
|
255334
|
+
if (shallowDiffByChannel2("segmentationMatrixIndices", layerScope, channelScope) || shallowDiffByChannel2("segmentationMultiExpressionData", layerScope, channelScope)) {
|
|
255269
255335
|
this.onUpdateSegmentationsExpressionData(layerScope, channelScope);
|
|
255270
255336
|
forceUpdate = true;
|
|
255271
255337
|
}
|
|
@@ -255519,12 +255585,12 @@ class ErrorBoundary extends React__default.Component {
|
|
|
255519
255585
|
}
|
|
255520
255586
|
}
|
|
255521
255587
|
const LazySpatialThree = React__default.lazy(async () => {
|
|
255522
|
-
const { SpatialWrapper: SpatialWrapper2 } = await import("./index-
|
|
255588
|
+
const { SpatialWrapper: SpatialWrapper2 } = await import("./index-CA6Y_Dls.js").then((n3) => n3.a);
|
|
255523
255589
|
return { default: SpatialWrapper2 };
|
|
255524
255590
|
});
|
|
255525
255591
|
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 }) }) }) }));
|
|
255526
255592
|
const LazySpatialAccelerated = React__default.lazy(async () => {
|
|
255527
|
-
const { SpatialWrapper: SpatialWrapper2 } = await import("./index-
|
|
255593
|
+
const { SpatialWrapper: SpatialWrapper2 } = await import("./index-gStG4FEQ.js");
|
|
255528
255594
|
return { default: SpatialWrapper2 };
|
|
255529
255595
|
});
|
|
255530
255596
|
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 }) }) }) }));
|
|
@@ -263597,7 +263663,7 @@ _defineProperty$3(WindowScroller, "defaultProps", {
|
|
|
263597
263663
|
serverHeight: 0,
|
|
263598
263664
|
serverWidth: 0
|
|
263599
263665
|
});
|
|
263600
|
-
const useStyles$
|
|
263666
|
+
const useStyles$p = makeStyles()((theme) => ({
|
|
263601
263667
|
selectableTable: {
|
|
263602
263668
|
flex: "1 1 auto",
|
|
263603
263669
|
outline: "none"
|
|
@@ -263746,7 +263812,7 @@ function SelectableTable(props) {
|
|
|
263746
263812
|
onChange(null);
|
|
263747
263813
|
}
|
|
263748
263814
|
}, [selectedRows, allowMultiple]);
|
|
263749
|
-
const { classes: classes2 } = useStyles$
|
|
263815
|
+
const { classes: classes2 } = useStyles$p();
|
|
263750
263816
|
const inputUuid = v4$1();
|
|
263751
263817
|
const rowRenderer = ({ index: index2, style: style2 }) => (
|
|
263752
263818
|
// eslint-disable-next-line jsx-a11y/interactive-supports-focus
|
|
@@ -263771,7 +263837,7 @@ const FEATURELIST_SORT_OPTIONS = [
|
|
|
263771
263837
|
"original"
|
|
263772
263838
|
];
|
|
263773
263839
|
const ALT_COLNAME = "Alternate ID";
|
|
263774
|
-
const useStyles$
|
|
263840
|
+
const useStyles$o = makeStyles()(() => ({
|
|
263775
263841
|
searchBar: {
|
|
263776
263842
|
marginTop: "10px",
|
|
263777
263843
|
marginLeft: "10px",
|
|
@@ -263784,7 +263850,7 @@ const useStyles$n = makeStyles()(() => ({
|
|
|
263784
263850
|
}));
|
|
263785
263851
|
function FeatureList(props) {
|
|
263786
263852
|
const { width: width2, height: height2, hasColorEncoding, geneList = [], featureLabelsMap, geneSelection = [], geneFilter = null, setGeneSelection, enableMultiSelect, showFeatureTable, featureListSort, featureListSortKey, hasFeatureLabels, primaryColumnName } = props;
|
|
263787
|
-
const { classes: classes2 } = useStyles$
|
|
263853
|
+
const { classes: classes2 } = useStyles$o();
|
|
263788
263854
|
const [searchTerm, setSearchTerm] = useState("");
|
|
263789
263855
|
const selectableTableSortKey = featureListSortKey === "featureIndex" ? "key" : "name";
|
|
263790
263856
|
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]);
|
|
@@ -263857,7 +263923,7 @@ function FeatureListOptions(props) {
|
|
|
263857
263923
|
id: `feature-list-show-alternative-ids-${featureListId}`
|
|
263858
263924
|
} } }) })] })] }) : null] });
|
|
263859
263925
|
}
|
|
263860
|
-
const useStyles$
|
|
263926
|
+
const useStyles$n = makeStyles()((theme) => ({
|
|
263861
263927
|
featureListContainer: {
|
|
263862
263928
|
width: "100%",
|
|
263863
263929
|
height: "100%",
|
|
@@ -263872,7 +263938,7 @@ function FeatureListSubscriber(props) {
|
|
|
263872
263938
|
const loaders = useLoaders();
|
|
263873
263939
|
const coordinationScopes = useCoordinationScopes(coordinationScopesRaw);
|
|
263874
263940
|
const [width2, height2, containerRef] = useGridItemSize();
|
|
263875
|
-
const { classes: classes2 } = useStyles$
|
|
263941
|
+
const { classes: classes2 } = useStyles$n();
|
|
263876
263942
|
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);
|
|
263877
263943
|
const variablesLabel = variablesLabelOverride || featureType;
|
|
263878
263944
|
const title2 = titleOverride || `${capitalize$3(variablesLabel)} List`;
|
|
@@ -264007,7 +264073,7 @@ const useSelectionSliderStyles = makeStyles()(() => ({
|
|
|
264007
264073
|
backgroundColor: "rgba(128, 128, 128, 0.7)"
|
|
264008
264074
|
}
|
|
264009
264075
|
}));
|
|
264010
|
-
const useStyles$
|
|
264076
|
+
const useStyles$m = makeStyles()((theme) => ({
|
|
264011
264077
|
paletteContainer: {
|
|
264012
264078
|
width: "70px",
|
|
264013
264079
|
height: "40px",
|
|
@@ -264028,10 +264094,10 @@ const useStyles$l = makeStyles()((theme) => ({
|
|
|
264028
264094
|
}
|
|
264029
264095
|
}));
|
|
264030
264096
|
const ColorPalette = ({ handleChange }) => {
|
|
264031
|
-
const { classes: classes2 } = useStyles$
|
|
264097
|
+
const { classes: classes2 } = useStyles$m();
|
|
264032
264098
|
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)) });
|
|
264033
264099
|
};
|
|
264034
|
-
const useStyles$
|
|
264100
|
+
const useStyles$l = makeStyles()(() => ({
|
|
264035
264101
|
menuButton: {
|
|
264036
264102
|
backgroundColor: "transparent"
|
|
264037
264103
|
},
|
|
@@ -264050,7 +264116,7 @@ function MuiSpan(props) {
|
|
|
264050
264116
|
}
|
|
264051
264117
|
function ChannelOptions$1({ handlePropertyChange, handleChannelRemove, handleIQRUpdate }) {
|
|
264052
264118
|
const [open2, setOpen] = useState(false);
|
|
264053
|
-
const { classes: classes2 } = useStyles$
|
|
264119
|
+
const { classes: classes2 } = useStyles$l();
|
|
264054
264120
|
const handleColorSelect = (color2) => {
|
|
264055
264121
|
handlePropertyChange("color", color2);
|
|
264056
264122
|
};
|
|
@@ -264667,7 +264733,7 @@ function LayerController$1(props) {
|
|
|
264667
264733
|
minWidth: "50%"
|
|
264668
264734
|
} })] }), 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] })] });
|
|
264669
264735
|
}
|
|
264670
|
-
const useStyles$
|
|
264736
|
+
const useStyles$k = makeStyles()(() => ({
|
|
264671
264737
|
addButton: {
|
|
264672
264738
|
marginTop: "10px",
|
|
264673
264739
|
marginBottom: "10px",
|
|
@@ -264679,7 +264745,7 @@ function ImageAddIcon() {
|
|
|
264679
264745
|
}
|
|
264680
264746
|
function ImageAddButton({ imageOptions, handleImageAdd }) {
|
|
264681
264747
|
const [open2, setOpen] = useState(false);
|
|
264682
|
-
const { classes: classes2 } = useStyles$
|
|
264748
|
+
const { classes: classes2 } = useStyles$k();
|
|
264683
264749
|
const handleAdd = (imgData) => {
|
|
264684
264750
|
setOpen((prev2) => !prev2);
|
|
264685
264751
|
handleImageAdd(imgData);
|
|
@@ -265011,7 +265077,7 @@ const useEllipsisMenuStyles = makeStyles()(() => ({
|
|
|
265011
265077
|
padding: "4px"
|
|
265012
265078
|
}
|
|
265013
265079
|
}));
|
|
265014
|
-
const useStyles$
|
|
265080
|
+
const useStyles$j = makeStyles()(() => ({
|
|
265015
265081
|
colorPickerPaper: {
|
|
265016
265082
|
overflow: "hidden",
|
|
265017
265083
|
"& > ul": {
|
|
@@ -265069,7 +265135,7 @@ function ChannelColorPickerMenu(props) {
|
|
|
265069
265135
|
setColor2([rgb2.r, rgb2.g, rgb2.b]);
|
|
265070
265136
|
}
|
|
265071
265137
|
}
|
|
265072
|
-
const { classes: classes2 } = useStyles$
|
|
265138
|
+
const { classes: classes2 } = useStyles$j();
|
|
265073
265139
|
const currentColor = color2 ? colorArrayToString(color2) : colorArrayToString(getDefaultColor(theme));
|
|
265074
265140
|
const isWritable = typeof setColor2 === "function";
|
|
265075
265141
|
const derivedOpen = isWritable ? isStaticColor && visible ? open2 : false : false;
|
|
@@ -265077,7 +265143,7 @@ function ChannelColorPickerMenu(props) {
|
|
|
265077
265143
|
[classes2.colorIconOutline]: theme !== "dark" && isEqual$3(color2, [255, 255, 255])
|
|
265078
265144
|
}), 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 }) });
|
|
265079
265145
|
}
|
|
265080
|
-
const useStyles$
|
|
265146
|
+
const useStyles$i = makeStyles()(() => ({
|
|
265081
265147
|
layerTypeSpotIcon: {
|
|
265082
265148
|
height: "100%",
|
|
265083
265149
|
marginLeft: "1px",
|
|
@@ -265090,7 +265156,7 @@ const useStyles$h = makeStyles()(() => ({
|
|
|
265090
265156
|
function SpotLayerEllipsisMenu(props) {
|
|
265091
265157
|
const { strokeWidth, setStrokeWidth, filled, setFilled, featureSelection, obsColorEncoding, setObsColorEncoding, featureValueColormap, setFeatureValueColormap, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible } = props;
|
|
265092
265158
|
const [open2, setOpen] = useState(false);
|
|
265093
|
-
const { classes: classes2 } = useStyles$
|
|
265159
|
+
const { classes: classes2 } = useStyles$i();
|
|
265094
265160
|
const { classes: selectClasses2 } = useSelectStyles();
|
|
265095
265161
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
265096
265162
|
const filledId = $bdb11010cef70236$export$f680877a34711e37();
|
|
@@ -265112,7 +265178,7 @@ function SpotLayerController(props) {
|
|
|
265112
265178
|
const Visibility = useMemo$1(() => visibleSetting ? VisibilityIcon : VisibilityOffIcon, [visibleSetting]);
|
|
265113
265179
|
const isStaticColor = obsColorEncoding === "spatialLayerColor";
|
|
265114
265180
|
const isColormap = obsColorEncoding === "geneSelection";
|
|
265115
|
-
const { classes: classes2 } = useStyles$
|
|
265181
|
+
const { classes: classes2 } = useStyles$i();
|
|
265116
265182
|
const { classes: lcClasses } = useControllerSectionStyles();
|
|
265117
265183
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
265118
265184
|
const handleVisibleChange = useCallback(() => {
|
|
@@ -265122,7 +265188,7 @@ function SpotLayerController(props) {
|
|
|
265122
265188
|
const handleOpacityChange = useCallback((e3, v) => setOpacity2(v), [setOpacity2]);
|
|
265123
265189
|
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 }) })] }) }) });
|
|
265124
265190
|
}
|
|
265125
|
-
const useStyles$
|
|
265191
|
+
const useStyles$h = makeStyles()(() => ({
|
|
265126
265192
|
layerFeatureControllerGrid: {
|
|
265127
265193
|
padding: "0",
|
|
265128
265194
|
flexWrap: "nowrap"
|
|
@@ -265167,14 +265233,15 @@ function LayerPerFeatureController(props) {
|
|
|
265167
265233
|
]);
|
|
265168
265234
|
}
|
|
265169
265235
|
}, [featureName, featureColor, setFeatureColor, featureColorIndex]);
|
|
265170
|
-
const { classes: classes2 } = useStyles$
|
|
265236
|
+
const { classes: classes2 } = useStyles$h();
|
|
265171
265237
|
const { classes: lcClasses } = useControllerSectionStyles();
|
|
265172
265238
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
265173
265239
|
const [open2, setOpen] = useState(false);
|
|
265174
265240
|
const { colorPickerColor, colorPickerReadable, colorPickerWritable, colorPickerTooltip } = useMemo$1(() => {
|
|
265175
265241
|
if (obsColorEncoding === "geneSelection") {
|
|
265242
|
+
const storedColor = featureColor?.find((fc) => fc.name === featureName)?.color;
|
|
265176
265243
|
return {
|
|
265177
|
-
colorPickerColor:
|
|
265244
|
+
colorPickerColor: storedColor ?? randomByFeatureColor ?? spatialLayerColor,
|
|
265178
265245
|
colorPickerReadable: true,
|
|
265179
265246
|
colorPickerWritable: true,
|
|
265180
265247
|
colorPickerTooltip: null
|
|
@@ -265220,7 +265287,7 @@ function LayerPerFeatureController(props) {
|
|
|
265220
265287
|
]);
|
|
265221
265288
|
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);
|
|
265222
265289
|
}
|
|
265223
|
-
const useStyles$
|
|
265290
|
+
const useStyles$g = makeStyles()(() => ({
|
|
265224
265291
|
pointLayerButton: {
|
|
265225
265292
|
borderStyle: "dashed",
|
|
265226
265293
|
marginTop: "10px",
|
|
@@ -265249,7 +265316,7 @@ const useStyles$f = makeStyles()(() => ({
|
|
|
265249
265316
|
}
|
|
265250
265317
|
}));
|
|
265251
265318
|
function PointLayerEllipsisMenu(props) {
|
|
265252
|
-
const { featureSelection, featureFilterMode, setFeatureFilterMode, obsColorEncoding, setObsColorEncoding, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible } = props;
|
|
265319
|
+
const { featureSelection, featureFilterMode, setFeatureFilterMode, obsColorEncoding, setObsColorEncoding, featureValueColormap, setFeatureValueColormap, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible } = props;
|
|
265253
265320
|
const [open2, setOpen] = useState(false);
|
|
265254
265321
|
const { classes: selectClasses2 } = useSelectStyles();
|
|
265255
265322
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
@@ -265259,7 +265326,8 @@ function PointLayerEllipsisMenu(props) {
|
|
|
265259
265326
|
const crosshairsVisibleId = $bdb11010cef70236$export$f680877a34711e37();
|
|
265260
265327
|
const legendVisibleId = $bdb11010cef70236$export$f680877a34711e37();
|
|
265261
265328
|
const featureFilterModeId = $bdb11010cef70236$export$f680877a34711e37();
|
|
265262
|
-
|
|
265329
|
+
const colormapSelectorId = $bdb11010cef70236$export$f680877a34711e37();
|
|
265330
|
+
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" } } })] })] });
|
|
265263
265331
|
}
|
|
265264
265332
|
function PointLayerController(props) {
|
|
265265
265333
|
const { theme, layerScope, layerCoordination, setLayerCoordination, palette = null, pointMatrixIndicesData, tiledPointsLoadingProgress, layerPerFeatureForPoints } = props;
|
|
@@ -265289,7 +265357,7 @@ function PointLayerController(props) {
|
|
|
265289
265357
|
}, [featureColor, featureSelection]);
|
|
265290
265358
|
const isStaticColor = obsColorEncoding === "spatialLayerColor" || obsColorEncoding === "geneSelection";
|
|
265291
265359
|
const showStaticColor = obsColorEncoding === "spatialLayerColor" || obsColorEncoding === "geneSelection" && hasUnspecifiedFeatureColors;
|
|
265292
|
-
const isColormap =
|
|
265360
|
+
const isColormap = obsColorEncoding === "geneSelection";
|
|
265293
265361
|
const hasSingleSelectedFeature = obsColorEncoding === "geneSelection" && Array.isArray(featureSelection) && featureSelection.length === 1;
|
|
265294
265362
|
const color2 = useMemo$1(() => {
|
|
265295
265363
|
if (showStaticColor) {
|
|
@@ -265336,7 +265404,7 @@ function PointLayerController(props) {
|
|
|
265336
265404
|
featureSelection,
|
|
265337
265405
|
showStaticColor
|
|
265338
265406
|
]);
|
|
265339
|
-
const { classes: classes2 } = useStyles$
|
|
265407
|
+
const { classes: classes2 } = useStyles$g();
|
|
265340
265408
|
const { classes: lcClasses } = useControllerSectionStyles();
|
|
265341
265409
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
265342
265410
|
const handleVisibleChange = useCallback(() => {
|
|
@@ -265348,9 +265416,24 @@ function PointLayerController(props) {
|
|
|
265348
265416
|
const [coloringTabIndex, setColoringTabIndex] = useState(0);
|
|
265349
265417
|
const { featureIndex } = pointMatrixIndicesData || {};
|
|
265350
265418
|
const hasSelectedFeatures = Array.isArray(featureSelection) && featureSelection.length > 0;
|
|
265351
|
-
|
|
265419
|
+
useEffect(() => {
|
|
265420
|
+
if (obsColorEncoding !== "geneSelection" || !Array.isArray(featureSelection))
|
|
265421
|
+
return;
|
|
265422
|
+
const cleanedFeatureColor = (featureColor ?? []).filter((fc) => featureSelection.includes(fc.name));
|
|
265423
|
+
const missingEntries = featureSelection.filter((featureName) => !cleanedFeatureColor.find((fc) => fc.name === featureName)).map((featureName) => {
|
|
265424
|
+
const varIdx = featureIndex?.indexOf(featureName) ?? -1;
|
|
265425
|
+
const fColor = varIdx >= 0 ? PALETTE[varIdx % PALETTE.length] : getDefaultColor(theme);
|
|
265426
|
+
return { name: featureName, color: fColor };
|
|
265427
|
+
});
|
|
265428
|
+
const nextFeatureColor = [...cleanedFeatureColor, ...missingEntries];
|
|
265429
|
+
const changed = nextFeatureColor.length !== featureColor?.length || missingEntries.length > 0;
|
|
265430
|
+
if (changed) {
|
|
265431
|
+
setFeatureColor(nextFeatureColor);
|
|
265432
|
+
}
|
|
265433
|
+
}, [featureSelection, obsColorEncoding, featureIndex, featureColor]);
|
|
265434
|
+
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] });
|
|
265352
265435
|
}
|
|
265353
|
-
const useStyles$
|
|
265436
|
+
const useStyles$f = makeStyles()(() => ({
|
|
265354
265437
|
layerTypeSegmentationIcon: {
|
|
265355
265438
|
height: "100%",
|
|
265356
265439
|
marginLeft: "1px",
|
|
@@ -265363,7 +265446,7 @@ const useStyles$e = makeStyles()(() => ({
|
|
|
265363
265446
|
function SegmentationChannelEllipsisMenu(props) {
|
|
265364
265447
|
const { obsType, featureType, featureValueType, strokeWidth, setStrokeWidth, filled, setFilled, featureSelection, obsColorEncoding, setObsColorEncoding, featureValueColormap, setFeatureValueColormap, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible } = props;
|
|
265365
265448
|
const [open2, setOpen] = useState(false);
|
|
265366
|
-
const { classes: classes2 } = useStyles$
|
|
265449
|
+
const { classes: classes2 } = useStyles$f();
|
|
265367
265450
|
const { classes: selectClasses2 } = useSelectStyles();
|
|
265368
265451
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
265369
265452
|
const filledId = $bdb11010cef70236$export$f680877a34711e37();
|
|
@@ -265382,7 +265465,7 @@ function SegmentationChannelController(props) {
|
|
|
265382
265465
|
const Visibility = useMemo$1(() => visibleSetting ? VisibilityIcon : VisibilityOffIcon, [visibleSetting]);
|
|
265383
265466
|
const isStaticColor = obsColorEncoding === "spatialChannelColor";
|
|
265384
265467
|
const isColormap = obsColorEncoding === "geneSelection";
|
|
265385
|
-
const { classes: classes2 } = useStyles$
|
|
265468
|
+
const { classes: classes2 } = useStyles$f();
|
|
265386
265469
|
const { classes: lcClasses } = useControllerSectionStyles();
|
|
265387
265470
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
265388
265471
|
const handleVisibleChange = useCallback(() => {
|
|
@@ -268100,7 +268183,7 @@ function useBaseQuery(options, Observer, queryClient) {
|
|
|
268100
268183
|
function useQuery(options, queryClient) {
|
|
268101
268184
|
return useBaseQuery(options, QueryObserver);
|
|
268102
268185
|
}
|
|
268103
|
-
const useStyles$
|
|
268186
|
+
const useStyles$e = makeStyles()(() => ({
|
|
268104
268187
|
channelMenuButton: {
|
|
268105
268188
|
backgroundColor: "transparent",
|
|
268106
268189
|
padding: "3px 0",
|
|
@@ -268114,7 +268197,7 @@ const useStyles$d = makeStyles()(() => ({
|
|
|
268114
268197
|
function ChannelOptions(props) {
|
|
268115
268198
|
const { onRemove: onRemove2, onResetWindowUsingIQR, showValueExtent, setShowValueExtent, numResolutions, spatialMaxResolution, setSpatialMaxResolution } = props;
|
|
268116
268199
|
const [open2, setOpen] = useState(false);
|
|
268117
|
-
const { classes: classes2 } = useStyles$
|
|
268200
|
+
const { classes: classes2 } = useStyles$e();
|
|
268118
268201
|
const { classes: selectClasses2 } = useSelectStyles();
|
|
268119
268202
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
268120
268203
|
function handleRemove() {
|
|
@@ -268127,7 +268210,7 @@ function ChannelOptions(props) {
|
|
|
268127
268210
|
const domainTypeId = $bdb11010cef70236$export$f680877a34711e37();
|
|
268128
268211
|
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" })] });
|
|
268129
268212
|
}
|
|
268130
|
-
const useStyles$
|
|
268213
|
+
const useStyles$d = makeStyles()(() => ({
|
|
268131
268214
|
channelSlider: {
|
|
268132
268215
|
marginTop: "7px"
|
|
268133
268216
|
}
|
|
@@ -268137,7 +268220,7 @@ function ChannelSlider(props) {
|
|
|
268137
268220
|
const rgbColor = toRgbUIString(colormapOn, color2, theme);
|
|
268138
268221
|
const dtype = image2?.getDtype();
|
|
268139
268222
|
const fullDomain = dtype ? DOMAINS[dtype] : [0, 0];
|
|
268140
|
-
const { classes: classes2 } = useStyles$
|
|
268223
|
+
const { classes: classes2 } = useStyles$d();
|
|
268141
268224
|
useEffect(() => {
|
|
268142
268225
|
if (!window2 && !disabled && Array.isArray(minMaxDomain)) {
|
|
268143
268226
|
setWindow2(minMaxDomain);
|
|
@@ -268152,7 +268235,7 @@ function ChannelSlider(props) {
|
|
|
268152
268235
|
return `${labelPrefix} for ${rgbColor} colormap channel`;
|
|
268153
268236
|
}, getAriaValueText: () => `Current colormap values: ${rgbColor}-${window2}`, min: min2, max: max2, step, orientation: "horizontal", className: classes2.channelSlider, style: { color: rgbColor }, disabled });
|
|
268154
268237
|
}
|
|
268155
|
-
const useStyles$
|
|
268238
|
+
const useStyles$c = makeStyles()(() => ({
|
|
268156
268239
|
visibilityCheckbox: {
|
|
268157
268240
|
padding: "10px 0"
|
|
268158
268241
|
}
|
|
@@ -268166,10 +268249,10 @@ function getCheckboxColor(colormapOn, color2, theme) {
|
|
|
268166
268249
|
function ChannelVisibilityCheckbox(props) {
|
|
268167
268250
|
const { color: color2, visible, setVisible, disabled, theme, colormapOn } = props;
|
|
268168
268251
|
const rgbColor = getCheckboxColor(colormapOn, color2, theme);
|
|
268169
|
-
const { classes: classes2 } = useStyles$
|
|
268252
|
+
const { classes: classes2 } = useStyles$c();
|
|
268170
268253
|
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" } } });
|
|
268171
268254
|
}
|
|
268172
|
-
const useStyles$
|
|
268255
|
+
const useStyles$b = makeStyles()(() => ({
|
|
268173
268256
|
oneLineChannelSelect: {
|
|
268174
268257
|
width: "90%",
|
|
268175
268258
|
marginLeft: "5%",
|
|
@@ -268178,7 +268261,7 @@ const useStyles$a = makeStyles()(() => ({
|
|
|
268178
268261
|
}));
|
|
268179
268262
|
function ChannelSelectionDropdown(props) {
|
|
268180
268263
|
const { featureIndex, channelsSortOrder, targetC, setTargetC, setWindow: setWindow2, disabled } = props;
|
|
268181
|
-
const { classes: classes2 } = useStyles$
|
|
268264
|
+
const { classes: classes2 } = useStyles$b();
|
|
268182
268265
|
const { classes: selectClasses2 } = useSelectStyles();
|
|
268183
268266
|
function handleChange(event2) {
|
|
268184
268267
|
setTargetC(event2.target.value === "" ? null : Number(event2.target.value));
|
|
@@ -268313,7 +268396,7 @@ function LoadingStatusIndicator(props) {
|
|
|
268313
268396
|
}
|
|
268314
268397
|
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 }) })] });
|
|
268315
268398
|
}
|
|
268316
|
-
const useStyles$
|
|
268399
|
+
const useStyles$a = makeStyles()(() => ({
|
|
268317
268400
|
imageLayerButton: {
|
|
268318
268401
|
borderStyle: "dashed",
|
|
268319
268402
|
marginTop: "10px",
|
|
@@ -268456,7 +268539,7 @@ function ImageLayerController(props) {
|
|
|
268456
268539
|
}, [visible, setVisible]);
|
|
268457
268540
|
const handleOpacityChange = useCallback((e3, v) => setOpacity2(v), [setOpacity2]);
|
|
268458
268541
|
const handleOpenChange = useCallback(() => setOpen((prev2) => !prev2), []);
|
|
268459
|
-
const { classes: classes2 } = useStyles$
|
|
268542
|
+
const { classes: classes2 } = useStyles$a();
|
|
268460
268543
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
268461
268544
|
const { classes: controllerSectionClasses } = useControllerSectionStyles();
|
|
268462
268545
|
const isMultiChannel = photometricInterpretation !== "RGB";
|
|
@@ -268468,7 +268551,7 @@ function ImageLayerController(props) {
|
|
|
268468
268551
|
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);
|
|
268469
268552
|
}), 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] }) });
|
|
268470
268553
|
}
|
|
268471
|
-
const useStyles$
|
|
268554
|
+
const useStyles$9 = makeStyles()((theme) => ({
|
|
268472
268555
|
dimensionsIcon: {
|
|
268473
268556
|
height: "40px",
|
|
268474
268557
|
width: "40px",
|
|
@@ -268492,7 +268575,7 @@ const useStyles$8 = makeStyles()((theme) => ({
|
|
|
268492
268575
|
function GlobalDimensionSlider(props) {
|
|
268493
268576
|
const { label: label2, targetValue, setTargetValue, min: min2 = 0, max: max2 = 0, spatialRenderingMode = null, setSpatialRenderingMode = null } = props;
|
|
268494
268577
|
const { classes: lcClasses } = useControllerSectionStyles();
|
|
268495
|
-
const { classes: classes2 } = useStyles$
|
|
268578
|
+
const { classes: classes2 } = useStyles$9();
|
|
268496
268579
|
const isForZ = spatialRenderingMode !== null;
|
|
268497
268580
|
const is3dMode = spatialRenderingMode === "3D";
|
|
268498
268581
|
function handleRenderingModeChange(event2) {
|
|
@@ -268503,17 +268586,112 @@ function GlobalDimensionSlider(props) {
|
|
|
268503
268586
|
}
|
|
268504
268587
|
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 })] }) }) });
|
|
268505
268588
|
}
|
|
268589
|
+
const useStyles$8 = makeStyles()(() => ({
|
|
268590
|
+
layerTypeCentroidSegmentationIcon: {
|
|
268591
|
+
height: "100%",
|
|
268592
|
+
marginLeft: "1px",
|
|
268593
|
+
fill: "currentColor",
|
|
268594
|
+
fontSize: "24px",
|
|
268595
|
+
width: "50%",
|
|
268596
|
+
maxWidth: "24px"
|
|
268597
|
+
},
|
|
268598
|
+
divider: {
|
|
268599
|
+
width: "1px",
|
|
268600
|
+
height: "20px",
|
|
268601
|
+
background: "currentColor",
|
|
268602
|
+
flexShrink: 0,
|
|
268603
|
+
margin: "0 10px"
|
|
268604
|
+
},
|
|
268605
|
+
inlineLabel: {
|
|
268606
|
+
margin: "0px !important",
|
|
268607
|
+
lineHeight: 1,
|
|
268608
|
+
alignSelf: "center"
|
|
268609
|
+
},
|
|
268610
|
+
iconCell: {
|
|
268611
|
+
display: "flex",
|
|
268612
|
+
alignItems: "center",
|
|
268613
|
+
justifyContent: "center"
|
|
268614
|
+
}
|
|
268615
|
+
}));
|
|
268616
|
+
function CombinedEllipsisMenu(props) {
|
|
268617
|
+
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;
|
|
268618
|
+
const [open2, setOpen] = useState(false);
|
|
268619
|
+
const { classes: selectClasses2 } = useSelectStyles();
|
|
268620
|
+
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
268621
|
+
const filledId = $bdb11010cef70236$export$f680877a34711e37();
|
|
268622
|
+
const strokeWidthId = $bdb11010cef70236$export$f680877a34711e37();
|
|
268623
|
+
const colorEncodingId = $bdb11010cef70236$export$f680877a34711e37();
|
|
268624
|
+
const colormapId = $bdb11010cef70236$export$f680877a34711e37();
|
|
268625
|
+
const colormapRangeId = $bdb11010cef70236$export$f680877a34711e37();
|
|
268626
|
+
const tooltipsId = $bdb11010cef70236$export$f680877a34711e37();
|
|
268627
|
+
const crosshairsId = $bdb11010cef70236$export$f680877a34711e37();
|
|
268628
|
+
const legendId = $bdb11010cef70236$export$f680877a34711e37();
|
|
268629
|
+
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) => {
|
|
268630
|
+
setFeatureValueColormap(e3.target.value);
|
|
268631
|
+
setPointFeatureValueColormap?.(e3.target.value);
|
|
268632
|
+
}, 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) => {
|
|
268633
|
+
setFeatureValueColormapRange(v);
|
|
268634
|
+
setPointFeatureValueColormapRange?.(v);
|
|
268635
|
+
}, 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 } } })] })] });
|
|
268636
|
+
}
|
|
268637
|
+
function SegmentationCentroidsController(props) {
|
|
268638
|
+
const { theme, segScope, segLayerCoordination, segChannelScopesByLayer, segChannelCoordination, pointScope, pointLayerCoordination } = props;
|
|
268639
|
+
const { classes: classes2 } = useStyles$8();
|
|
268640
|
+
const { classes: lcClasses } = useControllerSectionStyles();
|
|
268641
|
+
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
268642
|
+
const channelScopes = segChannelScopesByLayer?.[segScope] ?? [];
|
|
268643
|
+
const primaryChanScope = channelScopes[0];
|
|
268644
|
+
const chanValues = segChannelCoordination[0]?.[segScope]?.[primaryChanScope] ?? {};
|
|
268645
|
+
const chanSetters = segChannelCoordination[1]?.[segScope]?.[primaryChanScope] ?? {};
|
|
268646
|
+
const { obsType, featureType, featureValueType, spatialChannelVisible: segVisible, spatialChannelOpacity: segOpacity, spatialChannelColor: segColor, spatialSegmentationFilled: filled, spatialSegmentationStrokeWidth: strokeWidth, obsColorEncoding, featureSelection, featureValueColormap, featureValueColormapRange, tooltipsVisible, tooltipCrosshairsVisible, legendVisible } = chanValues;
|
|
268647
|
+
const { setSpatialChannelVisible: setSegVisible, setSpatialChannelOpacity: setSegOpacity, setSpatialChannelColor: setSegColor, setSpatialSegmentationFilled: setFilled, setSpatialSegmentationStrokeWidth: setStrokeWidth, setObsColorEncoding, setFeatureValueColormap, setFeatureValueColormapRange, setTooltipsVisible, setTooltipCrosshairsVisible, setLegendVisible } = chanSetters;
|
|
268648
|
+
const pointValues = pointLayerCoordination[0]?.[pointScope] ?? {};
|
|
268649
|
+
const pointSetters = pointLayerCoordination[1]?.[pointScope] ?? {};
|
|
268650
|
+
const { spatialLayerVisible: pointVisible, spatialLayerOpacity: pointOpacity, spatialLayerColor: pointColor, obsColorEncoding: pointObsColorEncoding, featureValueColormap: pointFeatureValueColormap } = pointValues;
|
|
268651
|
+
const { setSpatialLayerVisible: setPointVisible, setSpatialLayerOpacity: setPointOpacity, setSpatialLayerColor: setPointColor, setObsColorEncoding: setPointObsColorEncoding, setFeatureValueColormap: setPointFeatureValueColormap, setFeatureValueColormapRange: setPointFeatureValueColormapRange } = pointSetters;
|
|
268652
|
+
const sharedOpacity = segOpacity ?? 1;
|
|
268653
|
+
const handleOpacityChange = useCallback((e3, v) => {
|
|
268654
|
+
setSegOpacity?.(v);
|
|
268655
|
+
setPointOpacity?.(v);
|
|
268656
|
+
}, [setSegOpacity, setPointOpacity]);
|
|
268657
|
+
const handleSegVisibleChange = useCallback(() => {
|
|
268658
|
+
setSegVisible?.(typeof segVisible === "boolean" ? !segVisible : false);
|
|
268659
|
+
}, [segVisible, setSegVisible]);
|
|
268660
|
+
const handlePointVisibleChange = useCallback(() => {
|
|
268661
|
+
setPointVisible?.(typeof pointVisible === "boolean" ? !pointVisible : false);
|
|
268662
|
+
}, [pointVisible, setPointVisible]);
|
|
268663
|
+
const handleColorEncodingChange = useCallback((e3) => {
|
|
268664
|
+
const val = e3.target.value;
|
|
268665
|
+
setObsColorEncoding(val);
|
|
268666
|
+
if (val === "geneSelection") {
|
|
268667
|
+
setPointObsColorEncoding?.("geneSelection");
|
|
268668
|
+
} else if (val === "cellSetSelection") {
|
|
268669
|
+
setPointObsColorEncoding?.("cellSetSelection");
|
|
268670
|
+
} else {
|
|
268671
|
+
setPointObsColorEncoding?.("spatialChannelColor");
|
|
268672
|
+
}
|
|
268673
|
+
}, [setObsColorEncoding, setPointObsColorEncoding]);
|
|
268674
|
+
const segVisibleSetting = typeof segVisible === "boolean" ? segVisible : true;
|
|
268675
|
+
const pointVisibleSetting = typeof pointVisible === "boolean" ? pointVisible : true;
|
|
268676
|
+
const SegVisibility = segVisibleSetting ? VisibilityIcon : VisibilityOffIcon;
|
|
268677
|
+
const PointVisibility = pointVisibleSetting ? VisibilityIcon : VisibilityOffIcon;
|
|
268678
|
+
const isStaticColor = obsColorEncoding === "spatialChannelColor";
|
|
268679
|
+
const isColormap = obsColorEncoding === "geneSelection";
|
|
268680
|
+
const pointIsStaticColor = pointObsColorEncoding === "spatialChannelColor";
|
|
268681
|
+
const pointIsColormap = pointObsColorEncoding === "geneSelection";
|
|
268682
|
+
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 }) })] }) }) });
|
|
268683
|
+
}
|
|
268506
268684
|
function LayerController(props) {
|
|
268507
|
-
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;
|
|
268685
|
+
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;
|
|
268508
268686
|
const anyLayerHasT = Object.values(images || {}).some((image2) => image2?.image?.instance.hasTStack());
|
|
268509
268687
|
const anyLayerHasZ = Object.values(images || {}).some((image2) => image2?.image?.instance.hasZStack());
|
|
268510
268688
|
const maxT = Object.values(images || {}).reduce((a2, h2) => Math.max(a2, h2?.image?.instance.getNumT()), 1) - 1;
|
|
268511
268689
|
const maxZ = Object.values(images || {}).reduce((a2, h2) => Math.max(a2, h2?.image?.instance.getNumZ()), 1) - 1;
|
|
268512
268690
|
const reversedImageLayerScopes = useMemo$1(() => [...imageLayerScopes || []].reverse(), [imageLayerScopes]);
|
|
268513
|
-
const reversedSegmentationLayerScopes = useMemo$1(() => [...segmentationLayerScopes || []].reverse(), [segmentationLayerScopes]);
|
|
268514
268691
|
const reversedSpotLayerScopes = useMemo$1(() => [...spotLayerScopes || []].reverse(), [spotLayerScopes]);
|
|
268515
|
-
const reversedPointLayerScopes = useMemo$1(() => [...pointLayerScopes || []].reverse(), [pointLayerScopes]);
|
|
268516
|
-
|
|
268692
|
+
const reversedPointLayerScopes = useMemo$1(() => [...pointLayerScopes || []].filter((scope) => !pairedPointScopes.has(scope)).reverse(), [pointLayerScopes, pairedPointScopes]);
|
|
268693
|
+
const reversedSegmentationLayerScopes = useMemo$1(() => [...segmentationLayerScopes || []].filter((scope) => !pairedSegScopes.has(scope)).reverse(), [segmentationLayerScopes, pairedSegScopes]);
|
|
268694
|
+
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))] });
|
|
268517
268695
|
}
|
|
268518
268696
|
function LayerControllerSubscriber(props) {
|
|
268519
268697
|
const { coordinationScopes: coordinationScopesRaw, coordinationScopesBy: coordinationScopesByRaw, closeButtonVisible, downloadButtonVisible, removeGridComponent, theme, title: title2 = "Spatial Layers", uuid: uuid2, layerPerFeatureForPoints = false, cameraPresets, helpText = ViewHelpMapping.LAYER_CONTROLLER_BETA } = props;
|
|
@@ -268646,6 +268824,40 @@ function LayerControllerSubscriber(props) {
|
|
|
268646
268824
|
CoordinationType$1.TOOLTIP_CROSSHAIRS_VISIBLE,
|
|
268647
268825
|
CoordinationType$1.LEGEND_VISIBLE
|
|
268648
268826
|
], coordinationScopes, coordinationScopesBy, CoordinationType$1.POINT_LAYER);
|
|
268827
|
+
const centroidSegmentationPairs = React__default.useMemo(() => {
|
|
268828
|
+
const pairs = [];
|
|
268829
|
+
const pairedSegScopes = /* @__PURE__ */ new Set();
|
|
268830
|
+
const pairedPointScopes = /* @__PURE__ */ new Set();
|
|
268831
|
+
pointLayerScopes.forEach((pointScope) => {
|
|
268832
|
+
const pointCoord = pointLayerCoordination[0][pointScope];
|
|
268833
|
+
if (!pointCoord)
|
|
268834
|
+
return;
|
|
268835
|
+
const pointObsType = pointCoord[CoordinationType$1.OBS_TYPE];
|
|
268836
|
+
if (!pointObsType)
|
|
268837
|
+
return;
|
|
268838
|
+
const matchingSegScope = segmentationLayerScopes.find((segScope) => {
|
|
268839
|
+
if (pairedSegScopes.has(segScope))
|
|
268840
|
+
return false;
|
|
268841
|
+
const channelScopes = segmentationChannelScopesByLayer[segScope] || [];
|
|
268842
|
+
return channelScopes.some((chanScope) => {
|
|
268843
|
+
const chanCoord = segmentationChannelCoordination[0]?.[segScope]?.[chanScope];
|
|
268844
|
+
return chanCoord?.[CoordinationType$1.OBS_TYPE] === pointObsType;
|
|
268845
|
+
});
|
|
268846
|
+
});
|
|
268847
|
+
if (matchingSegScope) {
|
|
268848
|
+
pairs.push({ pointScope, segScope: matchingSegScope });
|
|
268849
|
+
pairedSegScopes.add(matchingSegScope);
|
|
268850
|
+
pairedPointScopes.add(pointScope);
|
|
268851
|
+
}
|
|
268852
|
+
});
|
|
268853
|
+
return { pairs, pairedSegScopes, pairedPointScopes };
|
|
268854
|
+
}, [
|
|
268855
|
+
pointLayerScopes,
|
|
268856
|
+
pointLayerCoordination,
|
|
268857
|
+
segmentationLayerScopes,
|
|
268858
|
+
segmentationChannelScopesByLayer,
|
|
268859
|
+
segmentationChannelCoordination
|
|
268860
|
+
]);
|
|
268649
268861
|
const [{ volumeLoadingProgress: volumeLoadingStatus, tiledPointsLoadingProgress }] = useAuxiliaryCoordination([
|
|
268650
268862
|
"spatialAcceleratedVolumeLoadingProgress",
|
|
268651
268863
|
"spatialTiledPointsLoadingProgress"
|
|
@@ -268673,7 +268885,7 @@ function LayerControllerSubscriber(props) {
|
|
|
268673
268885
|
imageDataStatus,
|
|
268674
268886
|
pointMultiIndicesDataStatus
|
|
268675
268887
|
]);
|
|
268676
|
-
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 }) });
|
|
268888
|
+
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 }) });
|
|
268677
268889
|
}
|
|
268678
268890
|
const isIterable$2 = (obj) => Symbol.iterator in obj;
|
|
268679
268891
|
const hasIterableEntries = (value2) => (
|
|
@@ -270588,7 +270800,7 @@ function HiglassGlobalStyles(props) {
|
|
|
270588
270800
|
}
|
|
270589
270801
|
register({ dataFetcher: ZarrMultivecDataFetcher_default, config: ZarrMultivecDataFetcher_default.config }, { pluginType: "dataFetcher" });
|
|
270590
270802
|
const LazyHiGlassComponent = React__default.lazy(async () => {
|
|
270591
|
-
const { HiGlassComponent } = await import("./higlass-
|
|
270803
|
+
const { HiGlassComponent } = await import("./higlass-CKuPDg4y.js");
|
|
270592
270804
|
return { default: HiGlassComponent };
|
|
270593
270805
|
});
|
|
270594
270806
|
const HG_SIZE = 800;
|
|
@@ -270926,6 +271138,12 @@ const useStyles$5 = makeStyles()(() => ({
|
|
|
270926
271138
|
neuroglancerWrapper: {
|
|
270927
271139
|
position: "relative",
|
|
270928
271140
|
height: "100%"
|
|
271141
|
+
},
|
|
271142
|
+
meshLoadingIndicator: {
|
|
271143
|
+
position: "absolute",
|
|
271144
|
+
bottom: 8,
|
|
271145
|
+
left: 8,
|
|
271146
|
+
zIndex: 50
|
|
270929
271147
|
}
|
|
270930
271148
|
}));
|
|
270931
271149
|
const globalNeuroglancerCss = `
|
|
@@ -273539,7 +273757,7 @@ function NeuroglancerGlobalStyles(props) {
|
|
|
273539
273757
|
const { classes: classes2 } = props;
|
|
273540
273758
|
return jsxs(Fragment, { children: [jsx$1(GlobalStyles$3, { styles: globalNeuroglancerCss }), jsx$1(ScopedGlobalStyles, { styles: globalNeuroglancerStyles, parentClassName: classes2.neuroglancerWrapper })] });
|
|
273541
273759
|
}
|
|
273542
|
-
const LazyReactNeuroglancer = React__default.lazy(() => import("./ReactNeuroglancer-
|
|
273760
|
+
const LazyReactNeuroglancer = React__default.lazy(() => import("./ReactNeuroglancer-C2C-vEVu.js"));
|
|
273543
273761
|
function createWorker() {
|
|
273544
273762
|
const worker = new WorkerFactory$1();
|
|
273545
273763
|
worker.AsyncComputationWorker = WorkerFactory;
|
|
@@ -273584,12 +273802,31 @@ class NeuroglancerComp extends PureComponent {
|
|
|
273584
273802
|
}
|
|
273585
273803
|
};
|
|
273586
273804
|
remapWheelToZoom(viewer.inputEventBindings.perspectiveView);
|
|
273805
|
+
const { getMeshIdToCellId, onViewerReady, cellsUrl } = this.props;
|
|
273587
273806
|
this.prevHoverHandler = () => {
|
|
273588
|
-
|
|
273589
|
-
|
|
273590
|
-
|
|
273807
|
+
const ms = viewer.mouseState;
|
|
273808
|
+
if (ms.pickedAnnotationId != null) {
|
|
273809
|
+
const byIdKey = String(ms.pickedAnnotationId);
|
|
273810
|
+
fetch(`${cellsUrl}/by_id/${byIdKey}`).then((r3) => r3.arrayBuffer()).then((buf) => {
|
|
273811
|
+
const dv = new DataView(buf);
|
|
273812
|
+
const actualMeshId = String(dv.getInt32(12, true));
|
|
273813
|
+
const cellId = getMeshIdToCellId?.(actualMeshId) ?? actualMeshId;
|
|
273814
|
+
this.latestOnSelectHoveredCoords?.(cellId);
|
|
273815
|
+
});
|
|
273816
|
+
return;
|
|
273817
|
+
}
|
|
273818
|
+
if (ms.pickedValue !== void 0 && ms.pickedValue !== null) {
|
|
273819
|
+
const meshId = String(ms.pickedValue?.low);
|
|
273820
|
+
const cellId = getMeshIdToCellId?.(meshId) ?? meshId;
|
|
273821
|
+
this.latestOnSelectHoveredCoords?.(cellId);
|
|
273822
|
+
return;
|
|
273591
273823
|
}
|
|
273824
|
+
this.latestOnSelectHoveredCoords?.(null);
|
|
273592
273825
|
};
|
|
273826
|
+
onViewerReady?.(() => {
|
|
273827
|
+
const panel = [...viewer.display.panels][0];
|
|
273828
|
+
return panel?.projectionParameters?.value_?.viewProjectionMat;
|
|
273829
|
+
});
|
|
273593
273830
|
viewer.mouseState.changed.add(this.prevHoverHandler);
|
|
273594
273831
|
} else {
|
|
273595
273832
|
if (this.prevMouseStateChanged && this.prevHoverHandler) {
|
|
@@ -273610,8 +273847,8 @@ class NeuroglancerComp extends PureComponent {
|
|
|
273610
273847
|
}
|
|
273611
273848
|
}
|
|
273612
273849
|
render() {
|
|
273613
|
-
const { classes: classes2, viewerState, cellColorMapping, onLayerLoadingChange } = this.props;
|
|
273614
|
-
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 }) }) })] });
|
|
273850
|
+
const { classes: classes2, viewerState, cellColorMapping, onLayerLoadingChange, onAnnotationSourceReady, onViewerReady, meshOpacity } = this.props;
|
|
273851
|
+
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 }) }) })] });
|
|
273615
273852
|
}
|
|
273616
273853
|
}
|
|
273617
273854
|
function useMemoCustomComparison(factory2, dependencies2, customIsEqual) {
|
|
@@ -273626,17 +273863,22 @@ function useMemoCustomComparison(factory2, dependencies2, customIsEqual) {
|
|
|
273626
273863
|
}
|
|
273627
273864
|
const shallowDiff = (prevDeps, nextDeps, depName) => prevDeps[depName] !== nextDeps[depName];
|
|
273628
273865
|
const shallowDiffByLayer = (prevDeps, nextDeps, depName, scopeName) => prevDeps?.[depName]?.[scopeName] !== nextDeps?.[depName]?.[scopeName];
|
|
273866
|
+
const shallowDiffByChannel = (prevDeps, nextDeps, depName, firstName, secondName) => prevDeps?.[depName]?.[firstName]?.[secondName] !== nextDeps?.[depName]?.[firstName]?.[secondName];
|
|
273629
273867
|
const shallowDiffByChannelWithKeys = (prevDeps, nextDeps, depName, firstName, secondName, keys2) => keys2.some((k) => prevDeps?.[depName]?.[firstName]?.[secondName]?.[k] !== nextDeps?.[depName]?.[firstName]?.[secondName]?.[k]);
|
|
273630
273868
|
const shallowDiffByLayerCoordinationWithKeys = (prevDeps, nextDeps, depName, layerScope, keys2) => keys2.some((k) => prevDeps?.[depName]?.[0]?.[layerScope]?.[k] !== nextDeps?.[depName]?.[0]?.[layerScope]?.[k]);
|
|
273631
273869
|
const shallowDiffByChannelCoordinationWithKeys = (prevDeps, nextDeps, depName, layerScope, channelScope, keys2) => keys2.some((k) => prevDeps?.[depName]?.[0]?.[layerScope]?.[channelScope]?.[k] !== nextDeps?.[depName]?.[0]?.[layerScope]?.[channelScope]?.[k]);
|
|
273632
273870
|
function customIsEqualForCellColors(prevDeps, nextDeps) {
|
|
273633
273871
|
let forceUpdate = false;
|
|
273634
273872
|
const curriedShallowDiff = (depName) => shallowDiff(prevDeps, nextDeps, depName);
|
|
273873
|
+
const curriedShallowDiffByChannel = (depName, firstName, secondName) => shallowDiffByChannel(prevDeps, nextDeps, depName, firstName, secondName);
|
|
273635
273874
|
const curriedShallowDiffByChannelWithKeys = (depName, firstName, secondName, keys2) => shallowDiffByChannelWithKeys(prevDeps, nextDeps, depName, firstName, secondName, keys2);
|
|
273636
273875
|
const curriedShallowDiffByChannelCoordinationWithKeys = (depName, layerScope, channelScope, keys2) => shallowDiffByChannelCoordinationWithKeys(prevDeps, nextDeps, depName, layerScope, channelScope, keys2);
|
|
273637
273876
|
if (curriedShallowDiff("theme")) {
|
|
273638
273877
|
forceUpdate = true;
|
|
273639
273878
|
}
|
|
273879
|
+
if (curriedShallowDiff("csvLoaded")) {
|
|
273880
|
+
forceUpdate = true;
|
|
273881
|
+
}
|
|
273640
273882
|
if (["segmentationLayerScopes", "segmentationChannelScopesByLayer"].some(curriedShallowDiff)) {
|
|
273641
273883
|
forceUpdate = true;
|
|
273642
273884
|
} else {
|
|
@@ -273651,8 +273893,11 @@ function customIsEqualForCellColors(prevDeps, nextDeps) {
|
|
|
273651
273893
|
"obsSetSelection",
|
|
273652
273894
|
"additionalObsSets",
|
|
273653
273895
|
"spatialChannelColor",
|
|
273654
|
-
"spatialChannelOpacity"
|
|
273655
|
-
|
|
273896
|
+
"spatialChannelOpacity",
|
|
273897
|
+
"featureValueColormap",
|
|
273898
|
+
"featureValueColormapRange",
|
|
273899
|
+
"featureSelection"
|
|
273900
|
+
]) || curriedShallowDiffByChannel("segmentationMultiIndicesData", layerScope, channelScope) || curriedShallowDiffByChannel("segmentationMultiExpressionNormData", layerScope, channelScope)) {
|
|
273656
273901
|
forceUpdate = true;
|
|
273657
273902
|
}
|
|
273658
273903
|
});
|
|
@@ -273698,7 +273943,13 @@ function customIsEqualForInitialViewerState(prevDeps, nextDeps) {
|
|
|
273698
273943
|
"featureSelection",
|
|
273699
273944
|
"featureFilterMode",
|
|
273700
273945
|
"featureColor",
|
|
273701
|
-
"spatialPointStrokeWidth"
|
|
273946
|
+
"spatialPointStrokeWidth",
|
|
273947
|
+
"featureValueColormap",
|
|
273948
|
+
"featureValueColormapRange",
|
|
273949
|
+
"featureSelection",
|
|
273950
|
+
"obsSetColor",
|
|
273951
|
+
"obsSetSelection",
|
|
273952
|
+
"additionalObsSets"
|
|
273702
273953
|
]) || Math.abs(prevDeps?.pointLayerCoordination?.[0]?.[layerScope]?.spatialLayerOpacity - nextDeps?.pointLayerCoordination?.[0]?.[layerScope]?.spatialLayerOpacity) >= 0.05) {
|
|
273703
273954
|
forceUpdate = true;
|
|
273704
273955
|
}
|
|
@@ -273752,6 +274003,35 @@ function getSpatialLayerColorWithSelectionShader(staticColor, opacity2, featureI
|
|
|
273752
274003
|
}
|
|
273753
274004
|
`;
|
|
273754
274005
|
}
|
|
274006
|
+
function getObsSetSelectionFilteredShader(phenotypeColors, selectedIndices, opacity2, borderWidth = 0) {
|
|
274007
|
+
const numColors = phenotypeColors.length;
|
|
274008
|
+
const numSelected = selectedIndices.length;
|
|
274009
|
+
const normColors = phenotypeColors.map((c2) => normalizeColor(c2));
|
|
274010
|
+
const colorsDecl = `vec3 phenotypeColors[${numColors}] = vec3[${numColors}](${normColors.map((c2) => toVec3(c2)).join(", ")});`;
|
|
274011
|
+
const selectedDecl = `int selectedIndices[${numSelected}] = int[${numSelected}](${selectedIndices.join(", ")});`;
|
|
274012
|
+
return `
|
|
274013
|
+
void main() {
|
|
274014
|
+
int phenotype = prop_phenotype();
|
|
274015
|
+
${colorsDecl}
|
|
274016
|
+
${selectedDecl}
|
|
274017
|
+
bool isSelected = false;
|
|
274018
|
+
for (int i = 0; i < ${numSelected}; ++i) {
|
|
274019
|
+
if (phenotype == selectedIndices[i]) {
|
|
274020
|
+
isSelected = true;
|
|
274021
|
+
}
|
|
274022
|
+
}
|
|
274023
|
+
if (!isSelected) {
|
|
274024
|
+
discard;
|
|
274025
|
+
}
|
|
274026
|
+
vec3 color = vec3(0.5, 0.5, 0.5);
|
|
274027
|
+
if (phenotype >= 0 && phenotype < ${numColors}) {
|
|
274028
|
+
color = phenotypeColors[phenotype];
|
|
274029
|
+
}
|
|
274030
|
+
setColor(vec4(color, ${opacity2.toFixed(4)}));
|
|
274031
|
+
${borderWidthGlsl(borderWidth)}
|
|
274032
|
+
}
|
|
274033
|
+
`;
|
|
274034
|
+
}
|
|
273755
274035
|
function getSpatialLayerColorFilteredShader(staticColor, opacity2, featureIndices, featureIndexProp, borderWidth = 0) {
|
|
273756
274036
|
const normStatic = normalizeColor(staticColor);
|
|
273757
274037
|
const numFeatures = featureIndices.length;
|
|
@@ -273933,6 +274213,23 @@ function getRandomPerPointShader(opacity2, featureIndexProp, pointIndexProp, bor
|
|
|
273933
274213
|
}
|
|
273934
274214
|
`;
|
|
273935
274215
|
}
|
|
274216
|
+
function getQuantitativeColormapShader(quantitativeColorProp, opacity2, colormap = GLSL_COLORMAP_DEFAULT, colormapRange = [0, 1], borderWidth = 0, quantitativeColorMax = 1) {
|
|
274217
|
+
const [low, high] = colormapRange;
|
|
274218
|
+
const resolvedColormap = GLSL_COLORMAPS.includes(colormap) ? colormap : GLSL_COLORMAP_DEFAULT;
|
|
274219
|
+
return `
|
|
274220
|
+
#define COLORMAP_FUNC ${resolvedColormap}
|
|
274221
|
+
${colormaps$1}
|
|
274222
|
+
void main() {
|
|
274223
|
+
float rawVal = float(prop_${quantitativeColorProp}());
|
|
274224
|
+
float normalizedVal = rawVal / ${quantitativeColorMax.toFixed(4)};
|
|
274225
|
+
float t = (normalizedVal - ${low.toFixed(4)}) / max(${(high - low).toFixed(4)}, 0.0001);
|
|
274226
|
+
t = clamp(t, 0.0, 1.0);
|
|
274227
|
+
vec4 col = COLORMAP_FUNC(t);
|
|
274228
|
+
setColor(vec4(col.rgb, ${opacity2.toFixed(4)}));
|
|
274229
|
+
${borderWidthGlsl(borderWidth)}
|
|
274230
|
+
}
|
|
274231
|
+
`;
|
|
274232
|
+
}
|
|
273936
274233
|
function getRandomPerPointWithSelectionShader(featureIndices, defaultColor, opacity2, featureIndexProp, pointIndexProp, borderWidth = 0) {
|
|
273937
274234
|
const normDefault = normalizeColor(defaultColor);
|
|
273938
274235
|
const numFeatures = featureIndices.length;
|
|
@@ -273988,8 +274285,25 @@ function getRandomPerPointFilteredShader(featureIndices, opacity2, featureIndexP
|
|
|
273988
274285
|
}
|
|
273989
274286
|
`;
|
|
273990
274287
|
}
|
|
274288
|
+
function getObsSetSelectionShader(phenotypeColors, opacity2, borderWidth = 0) {
|
|
274289
|
+
const numColors = phenotypeColors.length;
|
|
274290
|
+
const normColors = phenotypeColors.map((c2) => normalizeColor(c2));
|
|
274291
|
+
const colorsDecl = `vec3 phenotypeColors[${numColors}] = vec3[${numColors}](${normColors.map((c2) => toVec3(c2)).join(", ")});`;
|
|
274292
|
+
return `
|
|
274293
|
+
void main() {
|
|
274294
|
+
int phenotype = prop_phenotype();
|
|
274295
|
+
${colorsDecl}
|
|
274296
|
+
vec3 color = ${toVec3(normalizeColor([128, 128, 128]))};
|
|
274297
|
+
if (phenotype >= 0 && phenotype < ${numColors}) {
|
|
274298
|
+
color = phenotypeColors[phenotype];
|
|
274299
|
+
}
|
|
274300
|
+
setColor(vec4(color, ${opacity2.toFixed(4)}));
|
|
274301
|
+
${borderWidthGlsl(borderWidth)}
|
|
274302
|
+
}
|
|
274303
|
+
`;
|
|
274304
|
+
}
|
|
273991
274305
|
function getPointsShader(layerCoordination) {
|
|
273992
|
-
const { theme, featureIndex, spatialLayerOpacity, obsColorEncoding, spatialLayerColor, featureSelection, featureFilterMode, featureColor, pointMarkerBorderWidth = 0, featureIndexProp, pointIndexProp } = layerCoordination;
|
|
274306
|
+
const { theme, featureIndex, spatialLayerOpacity, obsColorEncoding, spatialLayerColor, featureSelection, featureFilterMode, featureColor, pointMarkerBorderWidth = 0, featureIndexProp, pointIndexProp, quantitativeColorProp, featureValueColormap, featureValueColormapRange, obsSetColor, obsSetSelection, quantitativeColorMax, pointsAreSegmentationCentroids } = layerCoordination;
|
|
273993
274307
|
const defaultColor = getDefaultColor(theme);
|
|
273994
274308
|
const opacity2 = spatialLayerOpacity ?? 1;
|
|
273995
274309
|
const staticColor = Array.isArray(spatialLayerColor) && spatialLayerColor.length === 3 ? spatialLayerColor : defaultColor;
|
|
@@ -274013,7 +274327,7 @@ function getPointsShader(layerCoordination) {
|
|
|
274013
274327
|
}
|
|
274014
274328
|
return getSpatialLayerColorWithSelectionShader(staticColor, opacity2, featureIndices, defaultColor, featureIndexProp, pointMarkerBorderWidth);
|
|
274015
274329
|
}
|
|
274016
|
-
if (obsColorEncoding === "geneSelection") {
|
|
274330
|
+
if (obsColorEncoding === "geneSelection" && !pointsAreSegmentationCentroids) {
|
|
274017
274331
|
if (!featureIndexProp) {
|
|
274018
274332
|
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.");
|
|
274019
274333
|
}
|
|
@@ -274049,19 +274363,49 @@ function getPointsShader(layerCoordination) {
|
|
|
274049
274363
|
}
|
|
274050
274364
|
return getRandomPerPointWithSelectionShader(featureIndices, defaultColor, opacity2, featureIndexProp, pointIndexProp, pointMarkerBorderWidth);
|
|
274051
274365
|
}
|
|
274366
|
+
if (obsColorEncoding === "geneSelection" && pointsAreSegmentationCentroids) {
|
|
274367
|
+
if (!quantitativeColorProp) {
|
|
274368
|
+
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.");
|
|
274369
|
+
return getSpatialLayerColorShader(staticColor, opacity2, pointMarkerBorderWidth);
|
|
274370
|
+
}
|
|
274371
|
+
return getQuantitativeColormapShader(quantitativeColorProp, opacity2, featureValueColormap, featureValueColormapRange, pointMarkerBorderWidth, quantitativeColorMax);
|
|
274372
|
+
}
|
|
274373
|
+
if (obsColorEncoding === "cellSetSelection") {
|
|
274374
|
+
if (!obsSetColor || !obsSetSelection) {
|
|
274375
|
+
return getSpatialLayerColorShader(staticColor, opacity2, pointMarkerBorderWidth);
|
|
274376
|
+
}
|
|
274377
|
+
const colorByName = {};
|
|
274378
|
+
obsSetColor?.forEach(({ path: path2, color: color2 }) => {
|
|
274379
|
+
if (path2?.length > 1) {
|
|
274380
|
+
colorByName[path2[path2.length - 1]] = color2;
|
|
274381
|
+
}
|
|
274382
|
+
});
|
|
274383
|
+
const uniqueNames = Object.keys(colorByName).sort();
|
|
274384
|
+
const phenotypeColors = uniqueNames.map((name2) => colorByName[name2] ?? defaultColor);
|
|
274385
|
+
if (isFiltered) {
|
|
274386
|
+
const selectedNames = new Set(obsSetSelection?.map((path2) => path2[path2.length - 1]) ?? []);
|
|
274387
|
+
const selectedIndices = uniqueNames.map((name2, idx) => selectedNames.has(name2) ? idx : -1).filter((idx) => idx >= 0);
|
|
274388
|
+
if (selectedIndices.length === 0) {
|
|
274389
|
+
return "void main() { discard; }";
|
|
274390
|
+
}
|
|
274391
|
+
return getObsSetSelectionFilteredShader(phenotypeColors, selectedIndices, opacity2, pointMarkerBorderWidth);
|
|
274392
|
+
}
|
|
274393
|
+
return getObsSetSelectionShader(phenotypeColors, opacity2, pointMarkerBorderWidth);
|
|
274394
|
+
}
|
|
274052
274395
|
return getSpatialLayerColorShader(staticColor, opacity2, pointMarkerBorderWidth);
|
|
274053
274396
|
}
|
|
274397
|
+
const DEFAULT_NG_DIMENSIONS = {
|
|
274398
|
+
x: [1, "nm"],
|
|
274399
|
+
y: [1, "nm"],
|
|
274400
|
+
z: [1, "nm"]
|
|
274401
|
+
};
|
|
274054
274402
|
const DEFAULT_NG_PROPS = {
|
|
274055
274403
|
layout: "3d",
|
|
274056
274404
|
position: [0, 0, 0],
|
|
274057
274405
|
projectionOrientation: [0, 0, 0, 1],
|
|
274058
274406
|
projectionScale: 1024,
|
|
274059
274407
|
crossSectionScale: 1,
|
|
274060
|
-
dimensions:
|
|
274061
|
-
x: [1, "nm"],
|
|
274062
|
-
y: [1, "nm"],
|
|
274063
|
-
z: [1, "nm"]
|
|
274064
|
-
},
|
|
274408
|
+
dimensions: DEFAULT_NG_DIMENSIONS,
|
|
274065
274409
|
layers: []
|
|
274066
274410
|
};
|
|
274067
274411
|
function toPrecomputedSource(url) {
|
|
@@ -274079,6 +274423,15 @@ function toNgLayerName(dataType, layerScope, channelScope = null) {
|
|
|
274079
274423
|
}
|
|
274080
274424
|
throw new Error(`Unsupported data type: ${dataType}`);
|
|
274081
274425
|
}
|
|
274426
|
+
function pointsHaveMatchingSegmentation({ pointObsType, segmentationLayerScopes, segmentationChannelScopesByLayer, segmentationChannelCoordination }) {
|
|
274427
|
+
return segmentationLayerScopes.some((segmentationLayerScope) => {
|
|
274428
|
+
const segmentationChannelScopes = segmentationChannelScopesByLayer?.[segmentationLayerScope] || [];
|
|
274429
|
+
return segmentationChannelScopes.some((segmentationChannelScope) => {
|
|
274430
|
+
const segmentationObsType = segmentationChannelCoordination?.[0]?.[segmentationLayerScope]?.[segmentationChannelScope]?.obsType;
|
|
274431
|
+
return segmentationObsType && pointObsType && segmentationObsType === pointObsType;
|
|
274432
|
+
});
|
|
274433
|
+
});
|
|
274434
|
+
}
|
|
274082
274435
|
function useNeuroglancerViewerState(theme, showAxisLines, segmentationLayerScopes, segmentationChannelScopesByLayer, segmentationLayerCoordination, segmentationChannelCoordination, obsSegmentationsUrls, obsSegmentationsData, pointLayerScopes, pointLayerCoordination, obsPointsUrls, obsPointsData, pointMultiIndicesData) {
|
|
274083
274436
|
const viewerState = useMemoCustomComparison(() => {
|
|
274084
274437
|
let result = cloneDeep$1(DEFAULT_NG_PROPS);
|
|
@@ -274101,6 +274454,9 @@ function useNeuroglancerViewerState(theme, showAxisLines, segmentationLayerScope
|
|
|
274101
274454
|
} : toPrecomputedSource(layerUrl);
|
|
274102
274455
|
result = {
|
|
274103
274456
|
...result,
|
|
274457
|
+
showAxisLines,
|
|
274458
|
+
showDefaultAnnotations: false,
|
|
274459
|
+
// this removes the yellow box around pointsLayer
|
|
274104
274460
|
layers: [
|
|
274105
274461
|
...result.layers,
|
|
274106
274462
|
{
|
|
@@ -274124,9 +274480,27 @@ function useNeuroglancerViewerState(theme, showAxisLines, segmentationLayerScope
|
|
|
274124
274480
|
const layerCoordination = pointLayerCoordination[0][layerScope];
|
|
274125
274481
|
const layerData = obsPointsData[layerScope];
|
|
274126
274482
|
const layerUrl = obsPointsUrls[layerScope]?.[0]?.url;
|
|
274483
|
+
const ngOptions = layerData?.neuroglancerOptions;
|
|
274484
|
+
if (ngOptions?.transform?.matrix && ngOptions?.transform?.outputDimensions) {
|
|
274485
|
+
result = {
|
|
274486
|
+
...result,
|
|
274487
|
+
dimensions: ngOptions.transform.outputDimensions ?? DEFAULT_NG_DIMENSIONS
|
|
274488
|
+
};
|
|
274489
|
+
}
|
|
274490
|
+
const pointsAreSegmentationCentroids = pointsHaveMatchingSegmentation({
|
|
274491
|
+
pointObsType: layerCoordination?.obsType,
|
|
274492
|
+
segmentationLayerScopes,
|
|
274493
|
+
segmentationChannelScopesByLayer,
|
|
274494
|
+
segmentationChannelCoordination
|
|
274495
|
+
});
|
|
274127
274496
|
const featureIndex = pointMultiIndicesData[layerScope]?.featureIndex;
|
|
274128
274497
|
if (layerUrl && layerData) {
|
|
274129
|
-
const { spatialLayerVisible, spatialLayerOpacity, obsColorEncoding, spatialLayerColor, featureSelection, featureFilterMode, featureColor, spatialPointStrokeWidth } = layerCoordination || {};
|
|
274498
|
+
const { spatialLayerVisible, spatialLayerOpacity, obsColorEncoding, spatialLayerColor, featureSelection, featureFilterMode, featureColor, spatialPointStrokeWidth, featureValueColormap, featureValueColormapRange } = layerCoordination || {};
|
|
274499
|
+
const quantitativeColorMax = layerData.neuroglancerOptions?.quantitativeColorMax;
|
|
274500
|
+
if (!quantitativeColorMax && obsColorEncoding === "geneSelection") {
|
|
274501
|
+
console.warn("quantitativeColorMax not specified in options — defaulting to 1.0 (no normalization)");
|
|
274502
|
+
}
|
|
274503
|
+
const quantitativeColorMaxSelected = quantitativeColorMax ?? 1;
|
|
274130
274504
|
const shader = getPointsShader({
|
|
274131
274505
|
theme,
|
|
274132
274506
|
featureIndex,
|
|
@@ -274136,9 +274510,18 @@ function useNeuroglancerViewerState(theme, showAxisLines, segmentationLayerScope
|
|
|
274136
274510
|
featureSelection,
|
|
274137
274511
|
featureFilterMode,
|
|
274138
274512
|
featureColor,
|
|
274513
|
+
featureValueColormap,
|
|
274514
|
+
featureValueColormapRange,
|
|
274139
274515
|
featureIndexProp: layerData.neuroglancerOptions?.featureIndexProp,
|
|
274140
274516
|
pointIndexProp: layerData.neuroglancerOptions?.pointIndexProp,
|
|
274141
|
-
|
|
274517
|
+
quantitativeColorProp: layerData.neuroglancerOptions?.quantitativeColorProp,
|
|
274518
|
+
pointMarkerBorderWidth: spatialPointStrokeWidth ?? 0,
|
|
274519
|
+
obsSets: layerCoordination.obsSets,
|
|
274520
|
+
obsSetColor: layerCoordination.obsSetColor,
|
|
274521
|
+
obsSetSelection: layerCoordination.obsSetSelection,
|
|
274522
|
+
additionalObsSets: layerCoordination.additionalObsSets,
|
|
274523
|
+
quantitativeColorMax: quantitativeColorMaxSelected,
|
|
274524
|
+
pointsAreSegmentationCentroids
|
|
274142
274525
|
});
|
|
274143
274526
|
result = {
|
|
274144
274527
|
...result,
|
|
@@ -274151,7 +274534,13 @@ function useNeuroglancerViewerState(theme, showAxisLines, segmentationLayerScope
|
|
|
274151
274534
|
subsources: {
|
|
274152
274535
|
default: true
|
|
274153
274536
|
},
|
|
274154
|
-
enableDefaultSubsources: false
|
|
274537
|
+
enableDefaultSubsources: false,
|
|
274538
|
+
...ngOptions?.transform?.matrix ? {
|
|
274539
|
+
transform: {
|
|
274540
|
+
matrix: ngOptions.transform.matrix,
|
|
274541
|
+
outputDimensions: ngOptions.transform?.outputDimensions ?? result.dimensions
|
|
274542
|
+
}
|
|
274543
|
+
} : {}
|
|
274155
274544
|
},
|
|
274156
274545
|
tab: "annotations",
|
|
274157
274546
|
shader,
|
|
@@ -274159,7 +274548,7 @@ function useNeuroglancerViewerState(theme, showAxisLines, segmentationLayerScope
|
|
|
274159
274548
|
visible: spatialLayerVisible,
|
|
274160
274549
|
// Options from layerData.neuroglancerOptions
|
|
274161
274550
|
// like projectionAnnotationSpacing:
|
|
274162
|
-
projectionAnnotationSpacing:
|
|
274551
|
+
projectionAnnotationSpacing: ngOptions?.projectionAnnotationSpacing ?? 1
|
|
274163
274552
|
}
|
|
274164
274553
|
],
|
|
274165
274554
|
// TODO: is this needed?
|
|
@@ -274190,6 +274579,8 @@ function useNeuroglancerViewerState(theme, showAxisLines, segmentationLayerScope
|
|
|
274190
274579
|
}, customIsEqualForInitialViewerState);
|
|
274191
274580
|
return viewerState;
|
|
274192
274581
|
}
|
|
274582
|
+
const ANNOTATION_HEADER_OFFSET = 8;
|
|
274583
|
+
const GREY_HEX = "#323232";
|
|
274193
274584
|
const EPSILON_KEYS_MAPPING_NG = {
|
|
274194
274585
|
projectionScale: 100,
|
|
274195
274586
|
projectionOrientation: 0.02,
|
|
@@ -274210,6 +274601,17 @@ const multiplyQuat = (a2, b2) => {
|
|
|
274210
274601
|
const conjQuat = (q) => [-q[0], -q[1], -q[2], q[3]];
|
|
274211
274602
|
const rad2deg = (r3) => r3 * 180 / Math.PI;
|
|
274212
274603
|
const deg2rad = (d) => d * Math.PI / 180;
|
|
274604
|
+
function applyColormap(colormap, t4) {
|
|
274605
|
+
const tClamped = Math.max(0, Math.min(1, t4));
|
|
274606
|
+
const interpolators = {
|
|
274607
|
+
plasma: interpolatePlasma,
|
|
274608
|
+
viridis: interpolateViridis,
|
|
274609
|
+
jet: interpolateJet,
|
|
274610
|
+
greys: interpolateGreys
|
|
274611
|
+
};
|
|
274612
|
+
const fn2 = interpolators[colormap] ?? interpolateViridis;
|
|
274613
|
+
return fn2(tClamped);
|
|
274614
|
+
}
|
|
274213
274615
|
function valueGreaterThanEpsilon(a2, b2, epsilon3) {
|
|
274214
274616
|
if (Array.isArray(a2) && Array.isArray(b2) && a2.length === b2.length) {
|
|
274215
274617
|
return a2.some((val, i2) => Math.abs(val - b2[i2]) > epsilon3);
|
|
@@ -274276,13 +274678,57 @@ function makeVitNgZoomCalibrator(initialNgProjectionScale, initialDeckZoom = 0)
|
|
|
274276
274678
|
}
|
|
274277
274679
|
};
|
|
274278
274680
|
}
|
|
274681
|
+
function parseAnnotationChunkSegmentsWithPositions(buffer2, serializer2) {
|
|
274682
|
+
const dv = new DataView(buffer2);
|
|
274683
|
+
if (buffer2.byteLength <= 8)
|
|
274684
|
+
return [];
|
|
274685
|
+
const count2 = dv.getUint32(0, true);
|
|
274686
|
+
if (count2 === 0)
|
|
274687
|
+
return [];
|
|
274688
|
+
const numBytes = serializer2.serializedBytes;
|
|
274689
|
+
const properties2 = [null, null, null, null, null];
|
|
274690
|
+
const results = [];
|
|
274691
|
+
for (let i2 = 0; i2 < count2; i2++) {
|
|
274692
|
+
serializer2.deserialize(dv, ANNOTATION_HEADER_OFFSET, i2, count2, true, properties2);
|
|
274693
|
+
const phenotype = properties2[0];
|
|
274694
|
+
const segId = properties2[1];
|
|
274695
|
+
if (segId > 0) {
|
|
274696
|
+
const propBase = ANNOTATION_HEADER_OFFSET + i2 * numBytes;
|
|
274697
|
+
const x2 = dv.getFloat32(propBase + 0, true);
|
|
274698
|
+
const y2 = dv.getFloat32(propBase + 4, true);
|
|
274699
|
+
const z2 = dv.getFloat32(propBase + 8, true);
|
|
274700
|
+
if (x2 !== 0 || y2 !== 0 || z2 !== 0) {
|
|
274701
|
+
results.push({
|
|
274702
|
+
id: String(segId),
|
|
274703
|
+
// mesh segment ID - use for segments array
|
|
274704
|
+
phenotype: Number(phenotype),
|
|
274705
|
+
x: x2,
|
|
274706
|
+
y: y2,
|
|
274707
|
+
z: z2
|
|
274708
|
+
});
|
|
274709
|
+
}
|
|
274710
|
+
}
|
|
274711
|
+
}
|
|
274712
|
+
return results;
|
|
274713
|
+
}
|
|
274714
|
+
const remapCellColors = (ngCellColors, cellIdToMeshIdRef) => {
|
|
274715
|
+
const remapped = {};
|
|
274716
|
+
Object.entries(ngCellColors).forEach(([cellId, color2]) => {
|
|
274717
|
+
const meshId = cellIdToMeshIdRef.current[cellId] ?? cellId;
|
|
274718
|
+
remapped[meshId] = color2;
|
|
274719
|
+
});
|
|
274720
|
+
return remapped;
|
|
274721
|
+
};
|
|
274279
274722
|
const VITESSCE_INTERACTION_DELAY = 50;
|
|
274280
274723
|
const INIT_VIT_ZOOM = -3.6;
|
|
274281
274724
|
const ZOOM_EPS = 0.01;
|
|
274282
274725
|
const ROTATION_EPS = 1e-3;
|
|
274283
274726
|
const TARGET_EPS = 0.5;
|
|
274284
274727
|
const NG_ROT_COOLDOWN_MS = 120;
|
|
274728
|
+
const MESH_LOAD_THRESHOLD = 100;
|
|
274729
|
+
const MESH_LOADING_OVERLAY_TIMEOUT = 1500;
|
|
274285
274730
|
const GUIDE_URL = "https://vitessce.io/docs/ng-guide/";
|
|
274731
|
+
const MESH_OPACITY = 0.6;
|
|
274286
274732
|
const LAST_INTERACTION_SOURCE = {
|
|
274287
274733
|
vitessce: "vitessce",
|
|
274288
274734
|
neuroglancer: "neuroglancer"
|
|
@@ -274299,10 +274745,11 @@ function NeuroglancerSubscriber(props) {
|
|
|
274299
274745
|
downloadButtonVisible,
|
|
274300
274746
|
removeGridComponent,
|
|
274301
274747
|
theme,
|
|
274302
|
-
showAxisLines =
|
|
274748
|
+
showAxisLines = true,
|
|
274303
274749
|
title: title2 = "Spatial",
|
|
274304
274750
|
subtitle = "Powered by Neuroglancer",
|
|
274305
274751
|
helpText = ViewHelpMapping.NEUROGLANCER,
|
|
274752
|
+
meshLoadProjectionScaleThreshold,
|
|
274306
274753
|
// Note: this is a temporary mechanism
|
|
274307
274754
|
// to pass an initial NG camera state.
|
|
274308
274755
|
// Ideally, all camera state should be passed via
|
|
@@ -274313,6 +274760,32 @@ function NeuroglancerSubscriber(props) {
|
|
|
274313
274760
|
} = props;
|
|
274314
274761
|
const loaders = useLoaders();
|
|
274315
274762
|
const mergeCoordination = useMergeCoordination();
|
|
274763
|
+
const { classes: classes2 } = useStyles$5();
|
|
274764
|
+
const initialRotationPushedRef = useRef(false);
|
|
274765
|
+
const getViewProjectionMatRef = useRef(null);
|
|
274766
|
+
const obsIdToMeshIdRef = useRef({});
|
|
274767
|
+
const meshIdToCellIdRef = useRef({});
|
|
274768
|
+
const cellIdToMeshIdRef = useRef({});
|
|
274769
|
+
const ngRotPushAtRef = useRef(0);
|
|
274770
|
+
const lastInteractionSource = useRef(null);
|
|
274771
|
+
const applyNgUpdateTimeoutRef = useRef(null);
|
|
274772
|
+
const lastNgPushOrientationRef = useRef(null);
|
|
274773
|
+
const initialRenderCalibratorRef = useRef(null);
|
|
274774
|
+
const translationOffsetRef = useRef([0, 0, 0]);
|
|
274775
|
+
const zoomRafRef = useRef(null);
|
|
274776
|
+
const lastNgQuatRef = useRef([0, 0, 0, 1]);
|
|
274777
|
+
const lastNgScaleRef = useRef(null);
|
|
274778
|
+
const annotationInfoRef = useRef(null);
|
|
274779
|
+
const annotationTransformRef = useRef(null);
|
|
274780
|
+
const visibleSegmentIdsRef = useRef(null);
|
|
274781
|
+
const chunkCacheRef = useRef(/* @__PURE__ */ new Map());
|
|
274782
|
+
const resizeObserverRef = useRef(null);
|
|
274783
|
+
const [isLayersLoaded, setIsLayersLoaded] = useState(false);
|
|
274784
|
+
const [isMeshLoading, setIsMeshLoading] = useState(false);
|
|
274785
|
+
const [annotationReady, setAnnotationReady] = useState(false);
|
|
274786
|
+
const [csvLoaded, setCsvLoaded] = useState(false);
|
|
274787
|
+
const updateVisibleSegmentsThrottledRef = useRef(null);
|
|
274788
|
+
const viewportSizeRef = useRef({ width: 0, height: 0 });
|
|
274316
274789
|
const coordinationScopes = useCoordinationScopes(coordinationScopesRaw);
|
|
274317
274790
|
const coordinationScopesBy = useCoordinationScopesBy(coordinationScopes, coordinationScopesByRaw);
|
|
274318
274791
|
const [{
|
|
@@ -274344,6 +274817,19 @@ function NeuroglancerSubscriber(props) {
|
|
|
274344
274817
|
setSpatialRotationOrbit: setRotationOrbit,
|
|
274345
274818
|
setSpatialZoom: setZoom
|
|
274346
274819
|
}] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType$1.NEUROGLANCER], coordinationScopes);
|
|
274820
|
+
const csvUrlRef = useRef(null);
|
|
274821
|
+
const csvUrl = useMemo$1(() => {
|
|
274822
|
+
if (csvUrlRef.current)
|
|
274823
|
+
return csvUrlRef.current;
|
|
274824
|
+
const obsSetsMap = loaders?.[dataset]?.loaders?.obsSets;
|
|
274825
|
+
if (!obsSetsMap)
|
|
274826
|
+
return null;
|
|
274827
|
+
const firstLoader = obsSetsMap.values().next().value;
|
|
274828
|
+
const url = firstLoader?.url ?? null;
|
|
274829
|
+
if (url)
|
|
274830
|
+
csvUrlRef.current = url;
|
|
274831
|
+
return url;
|
|
274832
|
+
}, [loaders, dataset]);
|
|
274347
274833
|
const [ngWidth, ngHeight, containerRef] = useGridItemSize();
|
|
274348
274834
|
const [segmentationLayerScopes, segmentationChannelScopesByLayer] = useMultiCoordinationScopesSecondaryNonNull(CoordinationType$1.SEGMENTATION_CHANNEL, CoordinationType$1.SEGMENTATION_LAYER, coordinationScopes, coordinationScopesBy);
|
|
274349
274835
|
const pointLayerScopes = useMultiCoordinationScopesNonNull(CoordinationType$1.POINT_LAYER, coordinationScopes);
|
|
@@ -274372,7 +274858,9 @@ function NeuroglancerSubscriber(props) {
|
|
|
274372
274858
|
CoordinationType$1.OBS_HIGHLIGHT,
|
|
274373
274859
|
CoordinationType$1.TOOLTIPS_VISIBLE,
|
|
274374
274860
|
CoordinationType$1.TOOLTIP_CROSSHAIRS_VISIBLE,
|
|
274375
|
-
CoordinationType$1.LEGEND_VISIBLE
|
|
274861
|
+
CoordinationType$1.LEGEND_VISIBLE,
|
|
274862
|
+
CoordinationType$1.FEATURE_TYPE,
|
|
274863
|
+
CoordinationType$1.FEATURE_VALUE_TYPE
|
|
274376
274864
|
], coordinationScopes, coordinationScopesBy, CoordinationType$1.SEGMENTATION_LAYER, CoordinationType$1.SEGMENTATION_CHANNEL);
|
|
274377
274865
|
const pointLayerCoordination = useComplexCoordination([
|
|
274378
274866
|
CoordinationType$1.OBS_TYPE,
|
|
@@ -274389,7 +274877,10 @@ function NeuroglancerSubscriber(props) {
|
|
|
274389
274877
|
CoordinationType$1.TOOLTIPS_VISIBLE,
|
|
274390
274878
|
CoordinationType$1.TOOLTIP_CROSSHAIRS_VISIBLE,
|
|
274391
274879
|
CoordinationType$1.LEGEND_VISIBLE,
|
|
274392
|
-
CoordinationType$1.SPATIAL_POINT_STROKE_WIDTH
|
|
274880
|
+
CoordinationType$1.SPATIAL_POINT_STROKE_WIDTH,
|
|
274881
|
+
CoordinationType$1.OBS_SET_COLOR,
|
|
274882
|
+
CoordinationType$1.OBS_SET_SELECTION,
|
|
274883
|
+
CoordinationType$1.ADDITIONAL_OBS_SETS
|
|
274393
274884
|
], coordinationScopes, coordinationScopesBy, CoordinationType$1.POINT_LAYER);
|
|
274394
274885
|
const [obsPointsData, obsPointsDataStatus, obsPointsUrls, obsPointsErrors] = useMultiObsPoints(coordinationScopes, coordinationScopesBy, loaders, dataset, mergeCoordination, uuid2);
|
|
274395
274886
|
const [pointMultiIndicesData, pointMultiIndicesDataStatus, pointMultiIndicesDataErrors] = usePointMultiObsFeatureMatrixIndices(coordinationScopes, coordinationScopesBy, loaders, dataset);
|
|
@@ -274415,34 +274906,89 @@ function NeuroglancerSubscriber(props) {
|
|
|
274415
274906
|
segmentationMultiFeatureSelectionStatus,
|
|
274416
274907
|
segmentationMultiIndicesDataStatus
|
|
274417
274908
|
]);
|
|
274418
|
-
const
|
|
274909
|
+
const lastVitessceRotationRef = useRef({
|
|
274910
|
+
x: spatialRotationX,
|
|
274911
|
+
y: spatialRotationY,
|
|
274912
|
+
z: spatialRotationZ,
|
|
274913
|
+
orbit: spatialRotationOrbit
|
|
274914
|
+
});
|
|
274915
|
+
const prevCoordsRef = useRef({
|
|
274916
|
+
zoom: spatialZoom,
|
|
274917
|
+
rx: spatialRotationX,
|
|
274918
|
+
ry: spatialRotationY,
|
|
274919
|
+
rz: spatialRotationZ,
|
|
274920
|
+
orbit: spatialRotationOrbit,
|
|
274921
|
+
tx: spatialTargetX,
|
|
274922
|
+
ty: spatialTargetY
|
|
274923
|
+
});
|
|
274419
274924
|
const segmentationColorMapping = useMemoCustomComparison(() => {
|
|
274420
274925
|
const result = {};
|
|
274421
274926
|
segmentationLayerScopes?.forEach((layerScope) => {
|
|
274422
274927
|
result[layerScope] = {};
|
|
274423
274928
|
segmentationChannelScopesByLayer?.[layerScope]?.forEach((channelScope) => {
|
|
274424
|
-
const { obsSets: layerSets, obsIndex:
|
|
274425
|
-
const
|
|
274929
|
+
const { obsSets: layerSets, obsIndex: layerIndexFromSets } = obsSegmentationsSetsData?.[layerScope]?.[channelScope] || {};
|
|
274930
|
+
const layerIndex = layerIndexFromSets ?? null;
|
|
274931
|
+
const { obsSetColor, obsColorEncoding, obsSetSelection, additionalObsSets, spatialChannelColor, spatialChannelOpacity, featureValueColormap, featureValueColormapRange } = segmentationChannelCoordination[0][layerScope][channelScope];
|
|
274426
274932
|
if (obsColorEncoding === "spatialChannelColor") {
|
|
274427
|
-
if (
|
|
274933
|
+
if (spatialChannelColor) {
|
|
274428
274934
|
const hex2 = rgbToHex$1(spatialChannelColor);
|
|
274429
274935
|
const ngCellColors = {};
|
|
274430
|
-
if (
|
|
274431
|
-
|
|
274432
|
-
|
|
274433
|
-
|
|
274434
|
-
|
|
274435
|
-
|
|
274436
|
-
|
|
274437
|
-
|
|
274438
|
-
|
|
274439
|
-
|
|
274936
|
+
if (layerIndex) {
|
|
274937
|
+
if (obsSetSelection?.length > 0) {
|
|
274938
|
+
const mergedCellSets = mergeObsSets(layerSets, additionalObsSets);
|
|
274939
|
+
const selectedIds = /* @__PURE__ */ new Set();
|
|
274940
|
+
obsSetSelection.forEach((setPath) => {
|
|
274941
|
+
const rootNode = mergedCellSets?.tree?.find((n3) => n3.name === setPath[0]);
|
|
274942
|
+
const leafNode = setPath.length > 1 ? rootNode?.children?.find((n3) => n3.name === setPath[1]) : rootNode;
|
|
274943
|
+
leafNode?.set?.forEach(([id2]) => selectedIds.add(String(id2)));
|
|
274944
|
+
});
|
|
274945
|
+
layerIndex.forEach((id2) => {
|
|
274946
|
+
if (selectedIds.has(String(id2))) {
|
|
274947
|
+
ngCellColors[id2] = hex2;
|
|
274948
|
+
}
|
|
274949
|
+
});
|
|
274950
|
+
} else {
|
|
274951
|
+
layerIndex.forEach((id2) => {
|
|
274440
274952
|
ngCellColors[id2] = hex2;
|
|
274441
|
-
}
|
|
274442
|
-
}
|
|
274953
|
+
});
|
|
274954
|
+
}
|
|
274443
274955
|
}
|
|
274444
|
-
result[layerScope][channelScope] = ngCellColors;
|
|
274956
|
+
result[layerScope][channelScope] = remapCellColors(ngCellColors, cellIdToMeshIdRef);
|
|
274957
|
+
result[layerScope].opacity = spatialChannelOpacity ?? 1;
|
|
274958
|
+
result[layerScope].defaultColor = hex2;
|
|
274959
|
+
}
|
|
274960
|
+
} else if (obsColorEncoding === "geneSelection") {
|
|
274961
|
+
const instanceObsIndex = obsSegmentationsSetsData?.[layerScope]?.[channelScope]?.obsIndex;
|
|
274962
|
+
const matrixObsIndex = segmentationMultiIndicesData?.[layerScope]?.[channelScope]?.obsIndex;
|
|
274963
|
+
const expressionData = segmentationMultiExpressionNormData?.[layerScope]?.[channelScope];
|
|
274964
|
+
if (instanceObsIndex && matrixObsIndex && expressionData?.[0]) {
|
|
274965
|
+
const matrixIndexMap = new Map(matrixObsIndex.map((key2, i2) => {
|
|
274966
|
+
const normalizedKey = key2.replace(/^.*_/, "");
|
|
274967
|
+
return [normalizedKey, i2];
|
|
274968
|
+
}));
|
|
274969
|
+
const toMatrixIndex = instanceObsIndex.map((key2) => matrixIndexMap.get(String(key2)));
|
|
274970
|
+
const [low, high] = featureValueColormapRange ?? [0, 1];
|
|
274971
|
+
const ngCellColors = {};
|
|
274972
|
+
instanceObsIndex.forEach((id2, i2) => {
|
|
274973
|
+
const rowIndex = toMatrixIndex[i2];
|
|
274974
|
+
const rawVal = expressionData[0][rowIndex] ?? 0;
|
|
274975
|
+
const t4 = rawVal / 255;
|
|
274976
|
+
const tScaled = (t4 - low) / Math.max(high - low, 1e-4);
|
|
274977
|
+
const tClamped = Math.max(0, Math.min(1, tScaled));
|
|
274978
|
+
const color2 = applyColormap(featureValueColormap ?? "viridis", tClamped);
|
|
274979
|
+
ngCellColors[id2] = rgbToHex$1(color2);
|
|
274980
|
+
});
|
|
274981
|
+
result[layerScope][channelScope] = remapCellColors(ngCellColors, cellIdToMeshIdRef);
|
|
274982
|
+
result[layerScope].opacity = spatialChannelOpacity ?? 1;
|
|
274983
|
+
} else if (instanceObsIndex) {
|
|
274984
|
+
const fallbackColor = spatialChannelColor ? rgbToHex$1(spatialChannelColor) : GREY_HEX;
|
|
274985
|
+
const ngCellColors = {};
|
|
274986
|
+
instanceObsIndex.forEach((id2) => {
|
|
274987
|
+
ngCellColors[id2] = fallbackColor;
|
|
274988
|
+
});
|
|
274989
|
+
result[layerScope][channelScope] = remapCellColors(ngCellColors, cellIdToMeshIdRef);
|
|
274445
274990
|
result[layerScope].opacity = spatialChannelOpacity ?? 1;
|
|
274991
|
+
result[layerScope].defaultColor = fallbackColor;
|
|
274446
274992
|
}
|
|
274447
274993
|
} else if (layerSets && layerIndex) {
|
|
274448
274994
|
const mergedCellSets = mergeObsSets(layerSets, additionalObsSets);
|
|
@@ -274454,10 +275000,10 @@ function NeuroglancerSubscriber(props) {
|
|
|
274454
275000
|
theme
|
|
274455
275001
|
});
|
|
274456
275002
|
const ngCellColors = {};
|
|
274457
|
-
cellColors.forEach((color2,
|
|
274458
|
-
ngCellColors[
|
|
275003
|
+
cellColors.forEach((color2, id2) => {
|
|
275004
|
+
ngCellColors[id2] = rgbToHex$1(color2);
|
|
274459
275005
|
});
|
|
274460
|
-
result[layerScope][channelScope] = ngCellColors;
|
|
275006
|
+
result[layerScope][channelScope] = remapCellColors(ngCellColors, cellIdToMeshIdRef);
|
|
274461
275007
|
result[layerScope].opacity = spatialChannelOpacity ?? 1;
|
|
274462
275008
|
}
|
|
274463
275009
|
});
|
|
@@ -274470,14 +275016,201 @@ function NeuroglancerSubscriber(props) {
|
|
|
274470
275016
|
segmentationChannelScopesByLayer,
|
|
274471
275017
|
obsSegmentationsSetsData,
|
|
274472
275018
|
segmentationChannelCoordination,
|
|
274473
|
-
theme
|
|
275019
|
+
theme,
|
|
275020
|
+
segmentationMultiExpressionNormData,
|
|
275021
|
+
segmentationMultiIndicesData,
|
|
275022
|
+
csvLoaded
|
|
274474
275023
|
}, customIsEqualForCellColors);
|
|
274475
|
-
const
|
|
275024
|
+
const initialViewerState = useNeuroglancerViewerState(theme, showAxisLines, segmentationLayerScopes, segmentationChannelScopesByLayer, segmentationLayerCoordination, segmentationChannelCoordination, obsSegmentationsUrls, obsSegmentationsData, pointLayerScopes, pointLayerCoordination, obsPointsUrls, obsPointsData, pointMultiIndicesData);
|
|
274476
275025
|
const [latestViewerStateIteration, incrementLatestViewerStateIteration] = useReducer((x2) => x2 + 1, 0);
|
|
274477
275026
|
const latestViewerStateRef = useRef({
|
|
274478
|
-
...
|
|
275027
|
+
...initialViewerState,
|
|
274479
275028
|
...initialNgCameraState ?? {}
|
|
274480
275029
|
});
|
|
275030
|
+
useEffect(() => {
|
|
275031
|
+
if (!csvUrl)
|
|
275032
|
+
return;
|
|
275033
|
+
fetch(csvUrl).then((r3) => r3.text()).then((text2) => {
|
|
275034
|
+
const lines = text2.split("\n");
|
|
275035
|
+
const header = lines[0].split(",");
|
|
275036
|
+
const meshIdIdx = header.indexOf("MeshID");
|
|
275037
|
+
const cellIdIdx = header.indexOf("CellID");
|
|
275038
|
+
const meshMap = {};
|
|
275039
|
+
const cellMap = {};
|
|
275040
|
+
lines.slice(1).forEach((l2) => {
|
|
275041
|
+
const cols = l2.split(",");
|
|
275042
|
+
const meshId = cols[meshIdIdx]?.trim();
|
|
275043
|
+
const cellId = cols[cellIdIdx]?.trim();
|
|
275044
|
+
if (meshId && cellId) {
|
|
275045
|
+
meshMap[meshId] = cellId;
|
|
275046
|
+
cellMap[cellId] = meshId;
|
|
275047
|
+
}
|
|
275048
|
+
});
|
|
275049
|
+
meshIdToCellIdRef.current = meshMap;
|
|
275050
|
+
cellIdToMeshIdRef.current = cellMap;
|
|
275051
|
+
setCsvLoaded(true);
|
|
275052
|
+
});
|
|
275053
|
+
}, [csvUrl]);
|
|
275054
|
+
useEffect(() => {
|
|
275055
|
+
chunkCacheRef.current.clear();
|
|
275056
|
+
}, [obsPointsData]);
|
|
275057
|
+
useEffect(() => {
|
|
275058
|
+
if (ngWidth && ngHeight) {
|
|
275059
|
+
viewportSizeRef.current = { width: ngWidth, height: ngHeight };
|
|
275060
|
+
}
|
|
275061
|
+
}, [ngWidth, ngHeight]);
|
|
275062
|
+
const setContainerNode = useCallback((node2) => {
|
|
275063
|
+
containerRef.current = node2;
|
|
275064
|
+
if (resizeObserverRef.current) {
|
|
275065
|
+
resizeObserverRef.current.disconnect();
|
|
275066
|
+
resizeObserverRef.current = null;
|
|
275067
|
+
}
|
|
275068
|
+
if (node2) {
|
|
275069
|
+
const rect2 = node2.getBoundingClientRect();
|
|
275070
|
+
if (rect2.width && rect2.height) {
|
|
275071
|
+
viewportSizeRef.current = { width: rect2.width, height: rect2.height };
|
|
275072
|
+
}
|
|
275073
|
+
const observer2 = new ResizeObserver((entries2) => {
|
|
275074
|
+
const entry2 = entries2[0];
|
|
275075
|
+
if (!entry2)
|
|
275076
|
+
return;
|
|
275077
|
+
const { width: width2, height: height2 } = entry2.contentRect;
|
|
275078
|
+
if (width2 && height2) {
|
|
275079
|
+
viewportSizeRef.current = { width: width2, height: height2 };
|
|
275080
|
+
}
|
|
275081
|
+
});
|
|
275082
|
+
observer2.observe(node2);
|
|
275083
|
+
resizeObserverRef.current = observer2;
|
|
275084
|
+
}
|
|
275085
|
+
}, []);
|
|
275086
|
+
const updateVisibleSegments = useCallback(async () => {
|
|
275087
|
+
if (!annotationInfoRef.current)
|
|
275088
|
+
return;
|
|
275089
|
+
if (!annotationTransformRef.current)
|
|
275090
|
+
return;
|
|
275091
|
+
if (!segmentationLayerScopes?.length)
|
|
275092
|
+
return;
|
|
275093
|
+
if (!pointLayerScopes?.length)
|
|
275094
|
+
return;
|
|
275095
|
+
const { position: position2, projectionScale } = latestViewerStateRef.current;
|
|
275096
|
+
if (!position2 || !projectionScale)
|
|
275097
|
+
return;
|
|
275098
|
+
const maxProjectionScale = meshLoadProjectionScaleThreshold ?? MESH_LOAD_THRESHOLD;
|
|
275099
|
+
if (projectionScale > maxProjectionScale) {
|
|
275100
|
+
if (visibleSegmentIdsRef.current?.length !== 0) {
|
|
275101
|
+
visibleSegmentIdsRef.current = [];
|
|
275102
|
+
incrementLatestViewerStateIteration();
|
|
275103
|
+
setIsMeshLoading(false);
|
|
275104
|
+
}
|
|
275105
|
+
return;
|
|
275106
|
+
}
|
|
275107
|
+
const { width: width2, height: height2 } = viewportSizeRef.current;
|
|
275108
|
+
if (!width2 || !height2)
|
|
275109
|
+
return;
|
|
275110
|
+
const transform3 = annotationTransformRef.current;
|
|
275111
|
+
const info2 = annotationInfoRef.current;
|
|
275112
|
+
const cellsUrl2 = info2.url;
|
|
275113
|
+
const allLevelCoords = info2.spatial.flatMap((level) => {
|
|
275114
|
+
const [gx, gy, gz] = level.grid_shape;
|
|
275115
|
+
const coords = [];
|
|
275116
|
+
for (let cx = 0; cx < gx; cx++) {
|
|
275117
|
+
for (let cy = 0; cy < gy; cy++) {
|
|
275118
|
+
for (let cz = 0; cz < gz; cz++) {
|
|
275119
|
+
coords.push({ level: level.key, cx, cy, cz });
|
|
275120
|
+
}
|
|
275121
|
+
}
|
|
275122
|
+
}
|
|
275123
|
+
return coords;
|
|
275124
|
+
});
|
|
275125
|
+
const fetchChunkWithPositions = async ({ level, cx, cy, cz }) => {
|
|
275126
|
+
const { serializers, serializer: defaultSerializer } = annotationTransformRef.current;
|
|
275127
|
+
const serializer2 = serializers?.[0] ?? defaultSerializer;
|
|
275128
|
+
if (!serializer2)
|
|
275129
|
+
return [];
|
|
275130
|
+
const cacheKey = `${cellsUrl2}/${level}/${cx}_${cy}_${cz}`;
|
|
275131
|
+
if (chunkCacheRef.current.has(cacheKey)) {
|
|
275132
|
+
return chunkCacheRef.current.get(cacheKey);
|
|
275133
|
+
}
|
|
275134
|
+
try {
|
|
275135
|
+
const res = await fetch(cacheKey);
|
|
275136
|
+
if (!res.ok) {
|
|
275137
|
+
chunkCacheRef.current.set(cacheKey, []);
|
|
275138
|
+
return [];
|
|
275139
|
+
}
|
|
275140
|
+
const buffer2 = await res.arrayBuffer();
|
|
275141
|
+
const entries2 = parseAnnotationChunkSegmentsWithPositions(buffer2, serializer2);
|
|
275142
|
+
chunkCacheRef.current.set(cacheKey, entries2);
|
|
275143
|
+
return entries2;
|
|
275144
|
+
} catch (e3) {
|
|
275145
|
+
chunkCacheRef.current.set(cacheKey, []);
|
|
275146
|
+
return [];
|
|
275147
|
+
}
|
|
275148
|
+
};
|
|
275149
|
+
try {
|
|
275150
|
+
const results = await Promise.all(allLevelCoords.map(fetchChunkWithPositions));
|
|
275151
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
275152
|
+
const allEntries = results.flat().filter(({ id: id2 }) => {
|
|
275153
|
+
if (seenIds.has(id2))
|
|
275154
|
+
return false;
|
|
275155
|
+
seenIds.add(id2);
|
|
275156
|
+
return true;
|
|
275157
|
+
});
|
|
275158
|
+
const obsIdToMeshId = {};
|
|
275159
|
+
allEntries.forEach(({ id: id2, obsId }) => {
|
|
275160
|
+
obsIdToMeshId[obsId] = id2;
|
|
275161
|
+
});
|
|
275162
|
+
obsIdToMeshIdRef.current = obsIdToMeshId;
|
|
275163
|
+
const mat = getViewProjectionMatRef.current?.();
|
|
275164
|
+
let visibleIds;
|
|
275165
|
+
if (!mat) {
|
|
275166
|
+
console.warn("No viewProjectionMatrix, loading all");
|
|
275167
|
+
visibleIds = [...new Set(allEntries.map(({ id: id2 }) => id2))];
|
|
275168
|
+
} else {
|
|
275169
|
+
const margin2 = Math.max(width2, height2) * 0.5;
|
|
275170
|
+
visibleIds = [...new Set(allEntries.filter(({ x: x2, y: y2, z: z2 }) => {
|
|
275171
|
+
const vx = x2 / transform3.x;
|
|
275172
|
+
const vy = y2 / transform3.y;
|
|
275173
|
+
const vz = (z2 || 0) / transform3.z;
|
|
275174
|
+
const cx = mat[0] * vx + mat[4] * vy + mat[8] * vz + mat[12];
|
|
275175
|
+
const cy = mat[1] * vx + mat[5] * vy + mat[9] * vz + mat[13];
|
|
275176
|
+
const cw2 = mat[3] * vx + mat[7] * vy + mat[11] * vz + mat[15];
|
|
275177
|
+
const screenX = (cx / cw2 + 1) * 0.5 * width2;
|
|
275178
|
+
const screenY = (1 - cy / cw2) * 0.5 * height2;
|
|
275179
|
+
return screenX >= -margin2 && screenX <= width2 + margin2 && screenY >= -margin2 && screenY <= height2 + margin2;
|
|
275180
|
+
}).map(({ id: id2 }) => id2))];
|
|
275181
|
+
}
|
|
275182
|
+
if (visibleIds.length === 0) {
|
|
275183
|
+
if (visibleSegmentIdsRef.current?.length !== 0) {
|
|
275184
|
+
visibleSegmentIdsRef.current = [];
|
|
275185
|
+
incrementLatestViewerStateIteration();
|
|
275186
|
+
}
|
|
275187
|
+
setIsMeshLoading(false);
|
|
275188
|
+
return;
|
|
275189
|
+
}
|
|
275190
|
+
const prevIds = new Set(visibleSegmentIdsRef.current ?? []);
|
|
275191
|
+
const addedIdsCount = visibleIds.filter((id2) => !prevIds.has(id2)).length;
|
|
275192
|
+
const hasSignificantChange = addedIdsCount > 20;
|
|
275193
|
+
if (hasSignificantChange && visibleIds.length > 0) {
|
|
275194
|
+
setIsMeshLoading(true);
|
|
275195
|
+
}
|
|
275196
|
+
const prevSorted = [...visibleSegmentIdsRef.current ?? []].sort().join(",");
|
|
275197
|
+
const nextSorted = [...visibleIds].sort().join(",");
|
|
275198
|
+
if (prevSorted !== nextSorted) {
|
|
275199
|
+
visibleSegmentIdsRef.current = visibleIds;
|
|
275200
|
+
incrementLatestViewerStateIteration();
|
|
275201
|
+
}
|
|
275202
|
+
if (hasSignificantChange) {
|
|
275203
|
+
setTimeout(() => setIsMeshLoading(false), MESH_LOADING_OVERLAY_TIMEOUT);
|
|
275204
|
+
}
|
|
275205
|
+
} catch (e3) {
|
|
275206
|
+
console.warn("[updateVisibleSegments] error:", e3);
|
|
275207
|
+
setIsMeshLoading(false);
|
|
275208
|
+
}
|
|
275209
|
+
}, [segmentationLayerScopes, pointLayerScopes, obsPointsData, meshLoadProjectionScaleThreshold]);
|
|
275210
|
+
useEffect(() => {
|
|
275211
|
+
updateVisibleSegmentsThrottledRef.current = throttle$1(updateVisibleSegments, 500);
|
|
275212
|
+
return () => updateVisibleSegmentsThrottledRef.current?.cancel();
|
|
275213
|
+
}, [updateVisibleSegments]);
|
|
274481
275214
|
useEffect(() => {
|
|
274482
275215
|
const prevNgCameraState = {
|
|
274483
275216
|
position: latestViewerStateRef.current.position,
|
|
@@ -274485,37 +275218,50 @@ function NeuroglancerSubscriber(props) {
|
|
|
274485
275218
|
projectionScale: latestViewerStateRef.current.projectionScale
|
|
274486
275219
|
};
|
|
274487
275220
|
latestViewerStateRef.current = {
|
|
274488
|
-
...
|
|
275221
|
+
...initialViewerState,
|
|
274489
275222
|
...prevNgCameraState
|
|
274490
275223
|
};
|
|
274491
275224
|
incrementLatestViewerStateIteration();
|
|
274492
|
-
}, [
|
|
274493
|
-
const
|
|
274494
|
-
|
|
274495
|
-
|
|
274496
|
-
|
|
274497
|
-
const
|
|
274498
|
-
|
|
274499
|
-
|
|
274500
|
-
|
|
274501
|
-
|
|
274502
|
-
|
|
274503
|
-
|
|
274504
|
-
|
|
274505
|
-
|
|
274506
|
-
|
|
274507
|
-
|
|
274508
|
-
|
|
274509
|
-
|
|
274510
|
-
|
|
274511
|
-
|
|
274512
|
-
|
|
274513
|
-
|
|
274514
|
-
|
|
274515
|
-
|
|
274516
|
-
|
|
274517
|
-
|
|
274518
|
-
|
|
275225
|
+
}, [initialViewerState]);
|
|
275226
|
+
const cellsUrl = useMemo$1(() => {
|
|
275227
|
+
const firstScope = pointLayerScopes?.[0];
|
|
275228
|
+
return obsPointsUrls?.[firstScope]?.[0]?.url ?? null;
|
|
275229
|
+
}, [pointLayerScopes, obsPointsUrls]);
|
|
275230
|
+
const hasMatchingAnnotationSource = useMemo$1(() => {
|
|
275231
|
+
if (!cellsUrl)
|
|
275232
|
+
return false;
|
|
275233
|
+
const firstPointScope = pointLayerScopes?.[0];
|
|
275234
|
+
return pointsHaveMatchingSegmentation({
|
|
275235
|
+
pointObsType: pointLayerCoordination[0]?.[firstPointScope]?.obsType,
|
|
275236
|
+
segmentationLayerScopes,
|
|
275237
|
+
segmentationChannelScopesByLayer,
|
|
275238
|
+
segmentationChannelCoordination
|
|
275239
|
+
});
|
|
275240
|
+
}, [cellsUrl, pointLayerScopes, segmentationLayerScopes, segmentationChannelScopesByLayer]);
|
|
275241
|
+
useEffect(() => {
|
|
275242
|
+
if (!cellsUrl)
|
|
275243
|
+
return;
|
|
275244
|
+
fetch(`${cellsUrl}/info`).then((r3) => r3.json()).then((info2) => {
|
|
275245
|
+
const infoWithUrl = {
|
|
275246
|
+
...info2,
|
|
275247
|
+
url: cellsUrl
|
|
275248
|
+
};
|
|
275249
|
+
annotationInfoRef.current = infoWithUrl;
|
|
275250
|
+
if (annotationTransformRef.current)
|
|
275251
|
+
setAnnotationReady(true);
|
|
275252
|
+
}).catch((err2) => console.error("failed to fetch annotation info:", err2));
|
|
275253
|
+
}, [cellsUrl]);
|
|
275254
|
+
useEffect(() => {
|
|
275255
|
+
if (annotationReady) {
|
|
275256
|
+
setIsLayersLoaded(true);
|
|
275257
|
+
updateVisibleSegments();
|
|
275258
|
+
}
|
|
275259
|
+
}, [annotationReady]);
|
|
275260
|
+
const onAnnotationSourceReady = useCallback((transform3) => {
|
|
275261
|
+
annotationTransformRef.current = transform3;
|
|
275262
|
+
if (annotationInfoRef.current)
|
|
275263
|
+
setAnnotationReady(true);
|
|
275264
|
+
}, []);
|
|
274519
275265
|
const handleStateUpdate = useCallback((newState) => {
|
|
274520
275266
|
lastInteractionSource.current = LAST_INTERACTION_SOURCE.neuroglancer;
|
|
274521
275267
|
const { projectionScale, projectionOrientation, position: position2 } = newState;
|
|
@@ -274548,6 +275294,7 @@ function NeuroglancerSubscriber(props) {
|
|
|
274548
275294
|
setZoom(vitZoomFromNg);
|
|
274549
275295
|
zoomRafRef.current = null;
|
|
274550
275296
|
});
|
|
275297
|
+
updateVisibleSegments();
|
|
274551
275298
|
}
|
|
274552
275299
|
lastNgScaleRef.current = projectionScale;
|
|
274553
275300
|
}
|
|
@@ -274588,7 +275335,8 @@ function NeuroglancerSubscriber(props) {
|
|
|
274588
275335
|
projectionScale,
|
|
274589
275336
|
position: position2
|
|
274590
275337
|
};
|
|
274591
|
-
|
|
275338
|
+
updateVisibleSegmentsThrottledRef.current?.();
|
|
275339
|
+
}, [updateVisibleSegmentsThrottledRef]);
|
|
274592
275340
|
const onSegmentClick = useCallback((value2) => {
|
|
274593
275341
|
if (value2) {
|
|
274594
275342
|
const id2 = String(value2);
|
|
@@ -274613,11 +275361,18 @@ function NeuroglancerSubscriber(props) {
|
|
|
274613
275361
|
const channelScope = segmentationChannelScopesByLayer?.[layerScope]?.[0];
|
|
274614
275362
|
result[layerScope] = {
|
|
274615
275363
|
colors: segmentationColorMapping?.[layerScope]?.[channelScope] ?? {},
|
|
274616
|
-
opacity: segmentationColorMapping?.[layerScope]?.opacity ?? 1
|
|
275364
|
+
opacity: segmentationColorMapping?.[layerScope]?.opacity ?? 1,
|
|
275365
|
+
defaultColor: segmentationColorMapping?.[layerScope]?.defaultColor ?? null
|
|
274617
275366
|
};
|
|
274618
275367
|
});
|
|
274619
275368
|
return result;
|
|
274620
275369
|
}, [segmentationColorMapping, segmentationLayerScopes, segmentationChannelScopesByLayer]);
|
|
275370
|
+
useEffect(() => {
|
|
275371
|
+
if (!hasMatchingAnnotationSource && isReady && !segmentationLayerScopes?.length) {
|
|
275372
|
+
setIsLayersLoaded(true);
|
|
275373
|
+
}
|
|
275374
|
+
}, [hasMatchingAnnotationSource, isReady, segmentationLayerScopes]);
|
|
275375
|
+
const meshOpacity = hasMatchingAnnotationSource ? MESH_OPACITY : void 0;
|
|
274621
275376
|
const derivedViewerState = useMemo$1(() => {
|
|
274622
275377
|
const { current: current2 } = latestViewerStateRef;
|
|
274623
275378
|
if (current2.layers.length <= 0) {
|
|
@@ -274676,13 +275431,33 @@ function NeuroglancerSubscriber(props) {
|
|
|
274676
275431
|
lastInteractionSource.current = null;
|
|
274677
275432
|
}
|
|
274678
275433
|
const updatedLayers = current2?.layers?.map((layer, idx) => {
|
|
274679
|
-
|
|
275434
|
+
if (layer.type !== "segmentation")
|
|
275435
|
+
return layer;
|
|
275436
|
+
const layerScope = segmentationLayerScopes?.find((scope) => layer.name?.includes(scope));
|
|
275437
|
+
if (!layerScope)
|
|
275438
|
+
return layer;
|
|
274680
275439
|
const layerColorMapping = cellColorMappingByLayer?.[layerScope]?.colors ?? {};
|
|
274681
|
-
const
|
|
275440
|
+
const defaultColor = cellColorMappingByLayer?.[layerScope]?.defaultColor;
|
|
275441
|
+
let segments2 = [];
|
|
275442
|
+
if (hasMatchingAnnotationSource) {
|
|
275443
|
+
segments2 = visibleSegmentIdsRef.current ?? [];
|
|
275444
|
+
} else if (Object.keys(layerColorMapping).length > 0) {
|
|
275445
|
+
segments2 = Object.keys(layerColorMapping);
|
|
275446
|
+
}
|
|
275447
|
+
let derivedSegmentColors = {};
|
|
275448
|
+
if (hasMatchingAnnotationSource && segments2.length > 0) {
|
|
275449
|
+
segments2.forEach((meshId) => {
|
|
275450
|
+
const color2 = layerColorMapping[meshId] || defaultColor;
|
|
275451
|
+
if (color2)
|
|
275452
|
+
derivedSegmentColors[meshId] = color2;
|
|
275453
|
+
});
|
|
275454
|
+
} else if (!hasMatchingAnnotationSource) {
|
|
275455
|
+
derivedSegmentColors = layerColorMapping;
|
|
275456
|
+
}
|
|
274682
275457
|
return {
|
|
274683
275458
|
...layer,
|
|
274684
|
-
segments:
|
|
274685
|
-
segmentColors:
|
|
275459
|
+
segments: segments2,
|
|
275460
|
+
segmentColors: derivedSegmentColors,
|
|
274686
275461
|
objectAlpha: cellColorMappingByLayer?.[layerScope]?.opacity ?? 1
|
|
274687
275462
|
};
|
|
274688
275463
|
}) ?? [];
|
|
@@ -274712,17 +275487,21 @@ function NeuroglancerSubscriber(props) {
|
|
|
274712
275487
|
spatialRotationZ,
|
|
274713
275488
|
spatialTargetX,
|
|
274714
275489
|
spatialTargetY,
|
|
274715
|
-
|
|
274716
|
-
latestViewerStateIteration
|
|
275490
|
+
initialViewerState,
|
|
275491
|
+
latestViewerStateIteration,
|
|
275492
|
+
hasMatchingAnnotationSource
|
|
274717
275493
|
]);
|
|
274718
275494
|
const onSegmentHighlight = useCallback((obsId) => {
|
|
274719
275495
|
setCellHighlight(String(obsId));
|
|
274720
275496
|
}, [setCellHighlight]);
|
|
274721
275497
|
const handleLayerLoadingChange = useCallback((isLoaded) => {
|
|
274722
|
-
|
|
274723
|
-
|
|
275498
|
+
if (!isLayersLoaded && isLoaded) {
|
|
275499
|
+
setIsLayersLoaded(true);
|
|
275500
|
+
}
|
|
275501
|
+
}, [isLayersLoaded]);
|
|
274724
275502
|
const hasLayers = derivedViewerState?.layers?.length > 0;
|
|
274725
|
-
|
|
275503
|
+
const showPointsLegend = !hasMatchingAnnotationSource;
|
|
275504
|
+
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, {
|
|
274726
275505
|
theme: "dark",
|
|
274727
275506
|
maxHeight: ngHeight,
|
|
274728
275507
|
// Segmentations
|
|
@@ -274731,10 +275510,12 @@ function NeuroglancerSubscriber(props) {
|
|
|
274731
275510
|
segmentationChannelScopesByLayer,
|
|
274732
275511
|
segmentationChannelCoordination,
|
|
274733
275512
|
// Points
|
|
274734
|
-
pointLayerScopes,
|
|
275513
|
+
pointLayerScopes: showPointsLegend ? pointLayerScopes : void 0,
|
|
274735
275514
|
pointLayerCoordination,
|
|
274736
275515
|
pointMultiIndicesData
|
|
274737
|
-
}) }), jsx$1(NeuroglancerComp, { classes: classes2, onSegmentClick, onSelectHoveredCoords: onSegmentHighlight, viewerState: derivedViewerState, cellColorMapping: cellColorMappingByLayer, setViewerState: handleStateUpdate, onLayerLoadingChange: handleLayerLoadingChange
|
|
275516
|
+
}) }), 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) => {
|
|
275517
|
+
getViewProjectionMatRef.current = getFn;
|
|
275518
|
+
}, getMeshIdToCellId: (meshId) => meshIdToCellIdRef.current[meshId], cellsUrl, meshOpacity })] }) : null });
|
|
274738
275519
|
}
|
|
274739
275520
|
const FEATURE_AGGREGATION_STRATEGIES = ["first", "last", "sum", "mean"];
|
|
274740
275521
|
function CellSetExpressionPlotOptions(props) {
|
|
@@ -327232,7 +328013,7 @@ const VEGA_THEMES = {
|
|
|
327232
328013
|
};
|
|
327233
328014
|
const DATASET_NAME = "table";
|
|
327234
328015
|
function VegaGlobalStyles() {
|
|
327235
|
-
const { theme } = useStyles$
|
|
328016
|
+
const { theme } = useStyles$z();
|
|
327236
328017
|
return jsx$1(GlobalStyles$3, { styles: {
|
|
327237
328018
|
"#vg-tooltip-element.vg-tooltip.custom-theme": {
|
|
327238
328019
|
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)",
|
|
@@ -327266,7 +328047,7 @@ function renderTooltipContents(tooltipText) {
|
|
|
327266
328047
|
}
|
|
327267
328048
|
function VegaPlot(props) {
|
|
327268
328049
|
const { spec: partialSpec, data: data2, getTooltipText, signalListeners, renderer = "svg", onNewView } = props;
|
|
327269
|
-
const { classes: tooltipClasses2 } = useStyles$
|
|
328050
|
+
const { classes: tooltipClasses2 } = useStyles$u();
|
|
327270
328051
|
const tooltipHandler = useMemo$1(() => {
|
|
327271
328052
|
if (typeof getTooltipText === "function") {
|
|
327272
328053
|
const tooltipConfig = {
|
|
@@ -353760,7 +354541,7 @@ function UncontrolledLauncher(props) {
|
|
|
353760
354541
|
));
|
|
353761
354542
|
}
|
|
353762
354543
|
export {
|
|
353763
|
-
|
|
354544
|
+
GREY_HEX as $,
|
|
353764
354545
|
require_descriptors as A,
|
|
353765
354546
|
BaseDecoder as B,
|
|
353766
354547
|
CoordinationType$1 as C,
|
|
@@ -353789,8 +354570,9 @@ export {
|
|
|
353789
354570
|
require_redefine as Z,
|
|
353790
354571
|
require_objectAssign as _,
|
|
353791
354572
|
getDefaultExportFromCjs$1 as a,
|
|
353792
|
-
|
|
353793
|
-
|
|
354573
|
+
diffCameraState as a0,
|
|
354574
|
+
UncontrolledLauncher as a1,
|
|
354575
|
+
ControlledLauncher as a2,
|
|
353794
354576
|
LercAddCompression as b,
|
|
353795
354577
|
commonjsGlobal$1 as c,
|
|
353796
354578
|
requireAssign as d,
|