@vitessce/all 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-o1KV1S6m.js → GeometryAndMeshXR-DngaDWBF.js} +1 -1
- package/dist/{ReactNeuroglancer-BuXB_Emb.js → ReactNeuroglancer-DSiLDSuM.js} +169 -57
- package/dist/{XREnterButton-DZUdn-IL.js → XREnterButton-Beha7PBD.js} +1 -1
- package/dist/{XRSceneComponents-Cgrg-9p2.js → XRSceneComponents-CNuqVsYi.js} +1 -1
- package/dist/{XRWrapper-BB28re-M.js → XRWrapper-BsV3wgJG.js} +2 -2
- package/dist/{deflate-E8TfyvM7.js → deflate-BnG3V84V.js} +1 -1
- package/dist/{higlass-CGhpbMxK.js → higlass-4OKx7mdy.js} +1 -1
- package/dist/{index-moreUHDf.js → index-B8FH88N6.js} +971 -189
- package/dist/{index-BHE3zASA.js → index-B9h9IQaz.js} +1 -1
- package/dist/{index-0nuepTVk.js → index-CwGBUQIk.js} +5 -5
- package/dist/index.js +8 -8
- package/dist/{jpeg-_87xUwY6.js → jpeg-9VJS3-Bw.js} +1 -1
- package/dist/{lerc-DFl9HcRa.js → lerc-D1J26SPX.js} +1 -1
- package/dist/{lzw-hla-j59h.js → lzw-xVcb3-tK.js} +1 -1
- package/dist/{packbits-C8umOnfG.js → packbits-Dm4fdK8S.js} +1 -1
- package/dist/{raw-BLQKlp_4.js → raw-UWcztCkw.js} +1 -1
- package/dist/{webimage-nk5eMN68.js → webimage-C-QWVV-f.js} +1 -1
- package/dist/{xrStore-gGt4Wkvz.js → xrStore-Dhi1LSJi.js} +1 -1
- package/dist-tsc/base-plugins.d.ts.map +1 -1
- package/package.json +33 -33
|
@@ -5440,12 +5440,12 @@ function baseIsEqual$3(value2, other, bitmask, customizer, stack2) {
|
|
|
5440
5440
|
var now$4 = function() {
|
|
5441
5441
|
return root$d.Date.now();
|
|
5442
5442
|
};
|
|
5443
|
-
var FUNC_ERROR_TEXT$
|
|
5443
|
+
var FUNC_ERROR_TEXT$3 = "Expected a function";
|
|
5444
5444
|
var nativeMax$3 = Math.max, nativeMin$1 = Math.min;
|
|
5445
5445
|
function debounce$5(func, wait2, options) {
|
|
5446
5446
|
var lastArgs, lastThis, maxWait, result, timerId, lastCallTime, lastInvokeTime = 0, leading = false, maxing = false, trailing = true;
|
|
5447
5447
|
if (typeof func != "function") {
|
|
5448
|
-
throw new TypeError(FUNC_ERROR_TEXT$
|
|
5448
|
+
throw new TypeError(FUNC_ERROR_TEXT$3);
|
|
5449
5449
|
}
|
|
5450
5450
|
wait2 = toNumber$3(wait2) || 0;
|
|
5451
5451
|
if (isObject$f(options)) {
|
|
@@ -5603,6 +5603,22 @@ var range$e = createRange();
|
|
|
5603
5603
|
function sum$6(array2) {
|
|
5604
5604
|
return array2 && array2.length ? baseSum(array2, identity$h) : 0;
|
|
5605
5605
|
}
|
|
5606
|
+
var FUNC_ERROR_TEXT$2 = "Expected a function";
|
|
5607
|
+
function throttle$1(func, wait2, options) {
|
|
5608
|
+
var leading = true, trailing = true;
|
|
5609
|
+
if (typeof func != "function") {
|
|
5610
|
+
throw new TypeError(FUNC_ERROR_TEXT$2);
|
|
5611
|
+
}
|
|
5612
|
+
if (isObject$f(options)) {
|
|
5613
|
+
leading = "leading" in options ? !!options.leading : leading;
|
|
5614
|
+
trailing = "trailing" in options ? !!options.trailing : trailing;
|
|
5615
|
+
}
|
|
5616
|
+
return debounce$5(func, wait2, {
|
|
5617
|
+
"leading": leading,
|
|
5618
|
+
"maxWait": wait2,
|
|
5619
|
+
"trailing": trailing
|
|
5620
|
+
});
|
|
5621
|
+
}
|
|
5606
5622
|
var INFINITY = 1 / 0;
|
|
5607
5623
|
var createSet = !(Set$3 && 1 / setToArray$2(new Set$3([, -0]))[1] == INFINITY) ? noop$h : function(values3) {
|
|
5608
5624
|
return new Set$3(values3);
|
|
@@ -10936,7 +10952,18 @@ const ngPrecomputedMeshSchema = z.object({
|
|
|
10936
10952
|
const ngPointAnnotationSchema = z.object({
|
|
10937
10953
|
projectionAnnotationSpacing: z.number(),
|
|
10938
10954
|
featureIndexProp: z.string().optional().describe("The name of the Neuroglancer AnnotationProperty containing feature IDs. For example, specify 'gene' to use prop_gene() in the Neuroglancer shader code."),
|
|
10939
|
-
pointIndexProp: z.string().optional().describe("The name of the Neuroglancer AnnotationProperty containing point IDs. For example, specify 'point_id' to use prop_point_id() in the Neuroglancer shader code.")
|
|
10955
|
+
pointIndexProp: z.string().optional().describe("The name of the Neuroglancer AnnotationProperty containing point IDs. For example, specify 'point_id' to use prop_point_id() in the Neuroglancer shader code."),
|
|
10956
|
+
transform: z.object({
|
|
10957
|
+
matrix: z.array(z.array(z.number())),
|
|
10958
|
+
outputDimensions: z.record(z.tuple([z.number(), z.string()]))
|
|
10959
|
+
}).optional().describe("A coordinate transformation matrix to apply to the annotation layer source to map annotation coordinates to the global coordinate space."),
|
|
10960
|
+
// Note: See comments in neuroglancer-sorger.js
|
|
10961
|
+
// We may remove these in the future, pending clarification
|
|
10962
|
+
// to questions in the tissue-map-tools repo
|
|
10963
|
+
// - https://github.com/hms-dbmi/tissue-map-tools/issues/20
|
|
10964
|
+
// - https://github.com/hms-dbmi/tissue-map-tools/issues/38
|
|
10965
|
+
quantitativeColorProp: z.string().optional(),
|
|
10966
|
+
quantitativeColorMax: z.number().optional()
|
|
10940
10967
|
}).partial().nullable();
|
|
10941
10968
|
const obsEmbeddingAnndataSchema = annDataObsEmbedding;
|
|
10942
10969
|
const obsSpotsAnndataSchema = annDataObsLocations;
|
|
@@ -18349,7 +18376,7 @@ const { tss } = createTss({
|
|
|
18349
18376
|
},
|
|
18350
18377
|
"usePlugin": useMuiThemeStyleOverridesPlugin
|
|
18351
18378
|
});
|
|
18352
|
-
const useStyles$
|
|
18379
|
+
const useStyles$y = tss.create({});
|
|
18353
18380
|
function createChainedFunction$1(...funcs) {
|
|
18354
18381
|
return funcs.reduce((acc, func) => {
|
|
18355
18382
|
if (func == null) {
|
|
@@ -72637,7 +72664,7 @@ const Popper = React.forwardRef((props, ref2) => {
|
|
|
72637
72664
|
}, [handlePopperRef]);
|
|
72638
72665
|
React.useImperativeHandle(popperRefProp, () => popperRef.current, []);
|
|
72639
72666
|
const [exited, setExited] = React.useState(true);
|
|
72640
|
-
const { theme } = useStyles$
|
|
72667
|
+
const { theme } = useStyles$y();
|
|
72641
72668
|
const rtlPlacement = flipPlacement(initialPlacement, theme);
|
|
72642
72669
|
const [placement, setPlacement] = React.useState(rtlPlacement);
|
|
72643
72670
|
React.useEffect(() => {
|
|
@@ -73371,7 +73398,7 @@ var VariableSizeList$1 = /* @__PURE__ */ createListComponent({
|
|
|
73371
73398
|
});
|
|
73372
73399
|
const VariableSizeList = VariableSizeList$1;
|
|
73373
73400
|
const LIST_ROW_HEIGHT$1 = 48;
|
|
73374
|
-
const useStyles$
|
|
73401
|
+
const useStyles$x = makeStyles()(() => ({
|
|
73375
73402
|
searchInput: {
|
|
73376
73403
|
lineHeight: "initial",
|
|
73377
73404
|
height: "auto !important"
|
|
@@ -73411,7 +73438,7 @@ const ListboxComponent$1 = React__default.forwardRef((props, ref2) => {
|
|
|
73411
73438
|
});
|
|
73412
73439
|
function SimpleAutocomplete(props) {
|
|
73413
73440
|
const { getMatches, onChange, textInputLabel = "Enter a gene", getItemLabel = (option) => option.label } = props;
|
|
73414
|
-
const { classes: classes2 } = useStyles$
|
|
73441
|
+
const { classes: classes2 } = useStyles$x();
|
|
73415
73442
|
const [potentialItems, setPotentialItems] = useState([]);
|
|
73416
73443
|
const handleInputChange = async (_event, value2) => {
|
|
73417
73444
|
if (!value2) {
|
|
@@ -82961,7 +82988,7 @@ function defaultUrlTransform(value2) {
|
|
|
82961
82988
|
}
|
|
82962
82989
|
return "";
|
|
82963
82990
|
}
|
|
82964
|
-
const useStyles$
|
|
82991
|
+
const useStyles$w = makeStyles()((theme) => ({
|
|
82965
82992
|
description: {
|
|
82966
82993
|
"& p, details, table": {
|
|
82967
82994
|
fontSize: "80%",
|
|
@@ -82998,7 +83025,7 @@ const useStyles$v = makeStyles()((theme) => ({
|
|
|
82998
83025
|
}));
|
|
82999
83026
|
function Description(props) {
|
|
83000
83027
|
const { description: description2, metadata: metadata2, descriptionType } = props;
|
|
83001
|
-
const { classes: classes2 } = useStyles$
|
|
83028
|
+
const { classes: classes2 } = useStyles$w();
|
|
83002
83029
|
return jsxs("div", { className: classes2.description, children: [descriptionType && descriptionType === DescriptionType.MARKDOWN ? jsx$1(Markdown, { children: description2 }) : jsx$1("p", { children: description2 }), metadata2 && Array.from(metadata2.entries()).map(([layerIndex, { name: layerName, metadata: metadataRecord }]) => metadataRecord && Object.entries(metadataRecord).length > 0 ? jsxs("details", { children: [jsx$1("summary", { children: layerName }), jsx$1("div", { className: classes2.metadataContainer, children: jsx$1("table", { children: jsx$1("tbody", { children: Object.entries(metadataRecord).map(([key2, value2]) => jsxs("tr", { children: [jsx$1("th", { title: key2, children: key2 }), jsx$1("td", { title: value2, children: value2 })] }, key2)) }) }) })] }, layerIndex) : null)] });
|
|
83003
83030
|
}
|
|
83004
83031
|
function DescriptionSubscriber(props) {
|
|
@@ -91250,6 +91277,37 @@ function dataToCellSetsTree(data2, options) {
|
|
|
91250
91277
|
return cellSetsTree;
|
|
91251
91278
|
}
|
|
91252
91279
|
const schemeRdBu = [[103, 0, 31], [178, 24, 43], [214, 96, 77], [244, 165, 130], [253, 219, 199], [247, 247, 247], [209, 229, 240], [146, 197, 222], [67, 147, 195], [33, 102, 172], [5, 48, 97]];
|
|
91280
|
+
const schemePlasma = [[13, 8, 135], [16, 7, 136], [19, 7, 137], [22, 7, 138], [25, 6, 140], [27, 6, 141], [29, 6, 142], [32, 6, 143], [34, 6, 144], [36, 6, 145], [38, 5, 145], [40, 5, 146], [42, 5, 147], [44, 5, 148], [46, 5, 149], [47, 5, 150], [49, 5, 151], [51, 5, 151], [53, 4, 152], [55, 4, 153], [56, 4, 154], [58, 4, 154], [60, 4, 155], [62, 4, 156], [63, 4, 156], [65, 4, 157], [67, 3, 158], [68, 3, 158], [70, 3, 159], [72, 3, 159], [73, 3, 160], [75, 3, 161], [76, 2, 161], [78, 2, 162], [80, 2, 162], [81, 2, 163], [83, 2, 163], [85, 2, 164], [86, 1, 164], [88, 1, 164], [89, 1, 165], [91, 1, 165], [92, 1, 166], [94, 1, 166], [96, 1, 166], [97, 0, 167], [99, 0, 167], [100, 0, 167], [102, 0, 167], [103, 0, 168], [105, 0, 168], [106, 0, 168], [108, 0, 168], [110, 0, 168], [111, 0, 168], [113, 0, 168], [114, 1, 168], [116, 1, 168], [117, 1, 168], [119, 1, 168], [120, 1, 168], [122, 2, 168], [123, 2, 168], [125, 3, 168], [126, 3, 168], [128, 4, 168], [129, 4, 167], [131, 5, 167], [132, 5, 167], [134, 6, 166], [135, 7, 166], [136, 8, 166], [138, 9, 165], [139, 10, 165], [141, 11, 165], [142, 12, 164], [143, 13, 164], [145, 14, 163], [146, 15, 163], [148, 16, 162], [149, 17, 161], [150, 19, 161], [152, 20, 160], [153, 21, 159], [154, 22, 159], [156, 23, 158], [157, 24, 157], [158, 25, 157], [160, 26, 156], [161, 27, 155], [162, 29, 154], [163, 30, 154], [165, 31, 153], [166, 32, 152], [167, 33, 151], [168, 34, 150], [170, 35, 149], [171, 36, 148], [172, 38, 148], [173, 39, 147], [174, 40, 146], [176, 41, 145], [177, 42, 144], [178, 43, 143], [179, 44, 142], [180, 46, 141], [181, 47, 140], [182, 48, 139], [183, 49, 138], [184, 50, 137], [186, 51, 136], [187, 52, 136], [188, 53, 135], [189, 55, 134], [190, 56, 133], [191, 57, 132], [192, 58, 131], [193, 59, 130], [194, 60, 129], [195, 61, 128], [196, 62, 127], [197, 64, 126], [198, 65, 125], [199, 66, 124], [200, 67, 123], [201, 68, 122], [202, 69, 122], [203, 70, 121], [204, 71, 120], [204, 73, 119], [205, 74, 118], [206, 75, 117], [207, 76, 116], [208, 77, 115], [209, 78, 114], [210, 79, 113], [211, 81, 113], [212, 82, 112], [213, 83, 111], [213, 84, 110], [214, 85, 109], [215, 86, 108], [216, 87, 107], [217, 88, 106], [218, 90, 106], [218, 91, 105], [219, 92, 104], [220, 93, 103], [221, 94, 102], [222, 95, 101], [222, 97, 100], [223, 98, 99], [224, 99, 99], [225, 100, 98], [226, 101, 97], [226, 102, 96], [227, 104, 95], [228, 105, 94], [229, 106, 93], [229, 107, 93], [230, 108, 92], [231, 110, 91], [231, 111, 90], [232, 112, 89], [233, 113, 88], [233, 114, 87], [234, 116, 87], [235, 117, 86], [235, 118, 85], [236, 119, 84], [237, 121, 83], [237, 122, 82], [238, 123, 81], [239, 124, 81], [239, 126, 80], [240, 127, 79], [240, 128, 78], [241, 129, 77], [241, 131, 76], [242, 132, 75], [243, 133, 75], [243, 135, 74], [244, 136, 73], [244, 137, 72], [245, 139, 71], [245, 140, 70], [246, 141, 69], [246, 143, 68], [247, 144, 68], [247, 145, 67], [247, 147, 66], [248, 148, 65], [248, 149, 64], [249, 151, 63], [249, 152, 62], [249, 154, 62], [250, 155, 61], [250, 156, 60], [250, 158, 59], [251, 159, 58], [251, 161, 57], [251, 162, 56], [252, 163, 56], [252, 165, 55], [252, 166, 54], [252, 168, 53], [252, 169, 52], [253, 171, 51], [253, 172, 51], [253, 174, 50], [253, 175, 49], [253, 177, 48], [253, 178, 47], [253, 180, 47], [253, 181, 46], [254, 183, 45], [254, 184, 44], [254, 186, 44], [254, 187, 43], [254, 189, 42], [254, 190, 42], [254, 192, 41], [253, 194, 41], [253, 195, 40], [253, 197, 39], [253, 198, 39], [253, 200, 39], [253, 202, 38], [253, 203, 38], [252, 205, 37], [252, 206, 37], [252, 208, 37], [252, 210, 37], [251, 211, 36], [251, 213, 36], [251, 215, 36], [250, 216, 36], [250, 218, 36], [249, 220, 36], [249, 221, 37], [248, 223, 37], [248, 225, 37], [247, 226, 37], [247, 228, 37], [246, 230, 38], [246, 232, 38], [245, 233, 38], [245, 235, 39], [244, 237, 39], [243, 238, 39], [243, 240, 39], [242, 242, 39], [241, 244, 38], [241, 245, 37], [240, 247, 36], [240, 249, 33]];
|
|
91281
|
+
const schemeViridis = [[68, 1, 84], [68, 2, 86], [69, 4, 87], [69, 5, 89], [70, 7, 90], [70, 8, 92], [70, 10, 93], [70, 11, 94], [71, 13, 96], [71, 14, 97], [71, 16, 99], [71, 17, 100], [71, 19, 101], [72, 20, 103], [72, 22, 104], [72, 23, 105], [72, 24, 106], [72, 26, 108], [72, 27, 109], [72, 28, 110], [72, 30, 111], [72, 31, 112], [72, 32, 113], [72, 34, 115], [72, 35, 116], [72, 36, 117], [72, 38, 118], [72, 39, 119], [72, 40, 120], [72, 42, 121], [72, 43, 122], [72, 44, 123], [72, 46, 124], [72, 47, 125], [72, 48, 126], [72, 50, 127], [72, 51, 128], [72, 52, 129], [72, 53, 130], [72, 55, 131], [72, 56, 132], [72, 57, 133], [72, 59, 134], [72, 60, 135], [72, 61, 136], [72, 63, 137], [72, 64, 137], [72, 65, 138], [72, 67, 139], [72, 68, 140], [72, 69, 141], [72, 71, 142], [72, 72, 143], [72, 73, 144], [72, 75, 145], [72, 76, 146], [72, 77, 147], [72, 79, 148], [72, 80, 149], [72, 82, 150], [72, 83, 150], [72, 84, 151], [72, 86, 152], [72, 87, 153], [72, 88, 154], [72, 90, 155], [71, 91, 156], [71, 92, 157], [71, 94, 158], [71, 95, 158], [71, 97, 159], [71, 98, 160], [71, 99, 161], [71, 101, 162], [71, 102, 163], [71, 103, 164], [71, 105, 164], [71, 106, 165], [71, 108, 166], [71, 109, 167], [71, 110, 168], [71, 112, 169], [71, 113, 169], [71, 114, 170], [71, 116, 171], [71, 117, 172], [70, 119, 173], [70, 120, 174], [70, 121, 174], [70, 123, 175], [70, 124, 176], [70, 125, 177], [70, 127, 178], [70, 128, 178], [70, 130, 179], [70, 131, 180], [70, 132, 181], [70, 134, 182], [70, 135, 182], [70, 136, 183], [70, 138, 184], [70, 139, 185], [70, 141, 186], [70, 142, 186], [70, 143, 187], [70, 145, 188], [70, 146, 189], [70, 148, 189], [70, 149, 190], [70, 150, 191], [70, 152, 192], [70, 153, 192], [70, 155, 193], [70, 156, 194], [70, 157, 195], [70, 159, 195], [70, 160, 196], [70, 162, 197], [70, 163, 198], [70, 164, 198], [70, 166, 199], [70, 167, 200], [71, 169, 200], [71, 170, 201], [71, 171, 202], [71, 173, 203], [71, 174, 203], [71, 176, 204], [71, 177, 205], [71, 178, 205], [72, 180, 206], [72, 181, 207], [72, 183, 207], [72, 184, 208], [73, 185, 209], [73, 187, 209], [73, 188, 210], [74, 190, 211], [74, 191, 211], [74, 192, 212], [75, 194, 213], [75, 195, 213], [76, 197, 214], [76, 198, 214], [77, 199, 215], [77, 201, 216], [78, 202, 216], [78, 204, 217], [79, 205, 217], [79, 207, 218], [80, 208, 218], [81, 209, 219], [81, 211, 220], [82, 212, 220], [83, 214, 221], [83, 215, 221], [84, 216, 222], [85, 218, 222], [85, 219, 223], [86, 221, 223], [87, 222, 224], [88, 224, 224], [88, 225, 225], [89, 226, 225], [90, 228, 226], [91, 229, 226], [92, 231, 227], [92, 232, 227], [93, 234, 228], [94, 235, 228], [95, 236, 229], [96, 238, 229], [97, 239, 230], [97, 241, 230], [98, 242, 231], [99, 244, 231], [100, 245, 232], [101, 246, 232], [102, 248, 233], [103, 249, 233], [104, 251, 234], [105, 252, 234]];
|
|
91282
|
+
const schemeJet = Array.from({ length: 256 }, (_, i2) => {
|
|
91283
|
+
const t4 = i2 / 255;
|
|
91284
|
+
let r3;
|
|
91285
|
+
let g2;
|
|
91286
|
+
let b2;
|
|
91287
|
+
if (t4 < 0.125) {
|
|
91288
|
+
r3 = 0;
|
|
91289
|
+
g2 = 0;
|
|
91290
|
+
b2 = 0.5 + t4 * 4;
|
|
91291
|
+
} else if (t4 < 0.375) {
|
|
91292
|
+
r3 = 0;
|
|
91293
|
+
g2 = (t4 - 0.125) * 4;
|
|
91294
|
+
b2 = 1;
|
|
91295
|
+
} else if (t4 < 0.625) {
|
|
91296
|
+
r3 = (t4 - 0.375) * 4;
|
|
91297
|
+
g2 = 1;
|
|
91298
|
+
b2 = 1 - (t4 - 0.375) * 4;
|
|
91299
|
+
} else if (t4 < 0.875) {
|
|
91300
|
+
r3 = 1;
|
|
91301
|
+
g2 = 1 - (t4 - 0.625) * 4;
|
|
91302
|
+
b2 = 0;
|
|
91303
|
+
} else {
|
|
91304
|
+
r3 = 1 - (t4 - 0.875) * 4;
|
|
91305
|
+
g2 = 0;
|
|
91306
|
+
b2 = 0;
|
|
91307
|
+
}
|
|
91308
|
+
return [Math.round(r3 * 255), Math.round(g2 * 255), Math.round(b2 * 255)];
|
|
91309
|
+
});
|
|
91310
|
+
const schemeGreys = Array.from({ length: 256 }, (_, i2) => [i2, i2, i2]);
|
|
91253
91311
|
function rgbSpline$1(spline) {
|
|
91254
91312
|
return (colors2) => {
|
|
91255
91313
|
const n3 = colors2.length;
|
|
@@ -91287,7 +91345,15 @@ function basis$2(values3) {
|
|
|
91287
91345
|
};
|
|
91288
91346
|
}
|
|
91289
91347
|
const interpolateRgbBasis = rgbSpline$1(basis$2);
|
|
91348
|
+
function interpolateSequentialMulti(range2) {
|
|
91349
|
+
const n3 = range2.length;
|
|
91350
|
+
return (t4) => range2[Math.max(0, Math.min(n3 - 1, Math.floor(t4 * n3)))];
|
|
91351
|
+
}
|
|
91290
91352
|
interpolateRgbBasis(schemeRdBu);
|
|
91353
|
+
const interpolatePlasma = interpolateSequentialMulti(schemePlasma);
|
|
91354
|
+
const interpolateViridis = interpolateSequentialMulti(schemeViridis);
|
|
91355
|
+
const interpolateJet = interpolateSequentialMulti(schemeJet);
|
|
91356
|
+
const interpolateGreys = interpolateSequentialMulti(schemeGreys);
|
|
91291
91357
|
function getCellColors(params2) {
|
|
91292
91358
|
const { cellSets, cellSetSelection, cellSetColor, obsIndex, theme } = params2;
|
|
91293
91359
|
if (cellSetSelection && cellSets) {
|
|
@@ -98069,7 +98135,7 @@ const Tooltip$2 = /* @__PURE__ */ React.forwardRef((props, ref2) => {
|
|
|
98069
98135
|
}, extraProps), getChildren());
|
|
98070
98136
|
});
|
|
98071
98137
|
const nodeHeight = 32;
|
|
98072
|
-
const useStyles$
|
|
98138
|
+
const useStyles$v = makeStyles()((theme) => ({
|
|
98073
98139
|
setsManager: {
|
|
98074
98140
|
position: "relative",
|
|
98075
98141
|
width: "100%",
|
|
@@ -98236,7 +98302,7 @@ const useStyles$u = makeStyles()((theme) => ({
|
|
|
98236
98302
|
}));
|
|
98237
98303
|
function SetsManagerTreeGlobalStyles(props) {
|
|
98238
98304
|
const { classes: classes2 } = props;
|
|
98239
|
-
const { theme } = useStyles$
|
|
98305
|
+
const { theme } = useStyles$y();
|
|
98240
98306
|
return jsx$1(ScopedGlobalStyles, { parentClassName: classes2.setsManagerTree, styles: {
|
|
98241
98307
|
".rc-tree": {
|
|
98242
98308
|
paddingLeft: "0",
|
|
@@ -98577,7 +98643,7 @@ function HelpTooltipGlobalStyles(props) {
|
|
|
98577
98643
|
}
|
|
98578
98644
|
function PopoverGlobalStyles(props) {
|
|
98579
98645
|
const { classes: classes2 } = props;
|
|
98580
|
-
const { theme } = useStyles$
|
|
98646
|
+
const { theme } = useStyles$y();
|
|
98581
98647
|
return jsx$1(ScopedGlobalStyles, { parentClassName: classes2.popover, styles: {
|
|
98582
98648
|
".rc-tooltip-inner": {
|
|
98583
98649
|
boxSizing: "border-box",
|
|
@@ -103261,7 +103327,7 @@ function NamedSetNodeStatic(props) {
|
|
|
103261
103327
|
const onClick = level === 0 && !expanded ? () => onCheckLevel(nodeKey, nextLevelToCheck) : () => onNodeView(path2);
|
|
103262
103328
|
const tooltipProps = disableTooltip ? { visible: false } : {};
|
|
103263
103329
|
const popoverMenuConfig = makeNodeViewMenuConfig(props);
|
|
103264
|
-
const { classes: classes2 } = useStyles$
|
|
103330
|
+
const { classes: classes2 } = useStyles$v();
|
|
103265
103331
|
return jsxs("span", { children: [jsx$1(HelpTooltip, { title: tooltipText, ...tooltipProps, children: jsx$1("button", { type: "button", onClick, onKeyPress: (e3) => callbackOnKeyPress(e3, "v", () => onNodeView(path2)), className: classes2.titleButton, children: title2 }) }), popoverMenuConfig.length > 0 ? jsx$1(PopoverMenu, { menuConfig: makeNodeViewMenuConfig(props), color: level > 0 && editable ? color2 || getDefaultColor(theme) : null, setColor: (c2) => onNodeSetColor(path2, c2), children: jsx$1("span", { children: jsx$1(SvgMenu, { className: classes2.nodeMenuIcon, "aria-label": "Open Node View Menu" }) }) }) : null, level > 0 && isChecking ? checkbox2 : null, level > 0 && jsx$1("span", { className: classes2.nodeSizeLabel, children: niceSize })] });
|
|
103266
103332
|
}
|
|
103267
103333
|
function NamedSetNodeEditing(props) {
|
|
@@ -103273,7 +103339,7 @@ function NamedSetNodeEditing(props) {
|
|
|
103273
103339
|
onNodeSetName(path2, currentTitle, true);
|
|
103274
103340
|
}
|
|
103275
103341
|
}
|
|
103276
|
-
const { classes: classes2 } = useStyles$
|
|
103342
|
+
const { classes: classes2 } = useStyles$v();
|
|
103277
103343
|
return jsxs("span", { className: classes2.titleButtonWithInput, children: [jsx$1("input", {
|
|
103278
103344
|
// eslint-disable-next-line jsx-a11y/no-autofocus
|
|
103279
103345
|
autoFocus: true,
|
|
@@ -103299,7 +103365,7 @@ function LevelsButtons(props) {
|
|
|
103299
103365
|
onCheckLevel(nodeKey, newLevel);
|
|
103300
103366
|
}
|
|
103301
103367
|
}
|
|
103302
|
-
const { classes: classes2 } = useStyles$
|
|
103368
|
+
const { classes: classes2 } = useStyles$v();
|
|
103303
103369
|
return jsx$1("div", { className: classes2.levelButtonsContainer, children: range$e(1, height2 + 1).map((i2) => {
|
|
103304
103370
|
const isChecked = isEqual$3(path2, checkedLevelPath) && i2 === checkedLevelIndex;
|
|
103305
103371
|
return jsx$1("div", { children: jsx$1(HelpTooltip, { title: getLevelTooltipText(i2), children: jsx$1("input", { className: clsx(classes2.levelRadioButton, { [classes2.levelRadioButtonChecked]: isChecked && !hasColorEncoding }), type: "checkbox", value: i2, checked: isChecked && hasColorEncoding, onChange: onCheck }) }) }, i2);
|
|
@@ -103383,7 +103449,7 @@ let TreeNode$1 = class TreeNode extends TreeNode$2 {
|
|
|
103383
103449
|
};
|
|
103384
103450
|
function PlusButton(props) {
|
|
103385
103451
|
const { datatype, onError, onImportTree, onCreateLevelZeroNode, importable, editable } = props;
|
|
103386
|
-
const { classes: classes2 } = useStyles$
|
|
103452
|
+
const { classes: classes2 } = useStyles$v();
|
|
103387
103453
|
const onImport = useCallback((importHandler, mimeType) => () => {
|
|
103388
103454
|
const uploadInputNode = document.createElement("input");
|
|
103389
103455
|
uploadInputNode.setAttribute("type", "file");
|
|
@@ -103500,7 +103566,7 @@ function SetsManager(props) {
|
|
|
103500
103566
|
}, onNodeCheckNewName, onNodeSetIsEditing: setIsEditingNodeName, onNodeRemove, onExportLevelZeroNodeJSON, onExportLevelZeroNodeTabular, onExportSetJSON, disableTooltip: isDragging, onDragStart: () => setIsDragging(true), onDragEnd: () => setIsDragging(false), children: renderTreeNodes(node2.children, readOnly, newPath) }, pathToKey(newPath));
|
|
103501
103567
|
});
|
|
103502
103568
|
}
|
|
103503
|
-
const { classes: classes2 } = useStyles$
|
|
103569
|
+
const { classes: classes2 } = useStyles$v();
|
|
103504
103570
|
return jsxs("div", { className: classes2.setsManager, children: [jsx$1(SetsManagerTreeGlobalStyles, { classes: classes2 }), jsxs("div", { className: classes2.setsManagerTree, children: [jsx$1(Tree$1, { draggable: false, checkable, checkedKeys: setSelectionKeys, expandedKeys: setExpansionKeys, autoExpandParent, onCheck: (checkedKeys, info2) => onCheckNode(info2.node.props.nodeKey, info2.checked), onExpand: (expandedKeys, info2) => onExpandNode(expandedKeys, info2.node.props.nodeKey, info2.expanded), children: renderTreeNodes(processedSets.tree, true, []) }), jsx$1(Tree$1, { draggable: true, checkable, checkedKeys: additionalSetSelectionKeys, expandedKeys: additionalSetExpansionKeys, autoExpandParent, onCheck: (checkedKeys, info2) => onCheckNode(info2.node.props.nodeKey, info2.checked), onExpand: (expandedKeys, info2) => onExpandNode(expandedKeys, info2.node.props.nodeKey, info2.expanded), onDrop: (info2) => {
|
|
103505
103571
|
const { eventKey: dropKey } = info2.node.props;
|
|
103506
103572
|
const { eventKey: dragKey } = info2.dragNode.props;
|
|
@@ -209465,22 +209531,22 @@ async function getDecoder(fileDirectory) {
|
|
|
209465
209531
|
const Decoder = await importFn();
|
|
209466
209532
|
return new Decoder(fileDirectory);
|
|
209467
209533
|
}
|
|
209468
|
-
addDecoder([void 0, 1], () => import("./raw-
|
|
209469
|
-
addDecoder(5, () => import("./lzw-
|
|
209534
|
+
addDecoder([void 0, 1], () => import("./raw-UWcztCkw.js").then((m2) => m2.default));
|
|
209535
|
+
addDecoder(5, () => import("./lzw-xVcb3-tK.js").then((m2) => m2.default));
|
|
209470
209536
|
addDecoder(6, () => {
|
|
209471
209537
|
throw new Error("old style JPEG compression is not supported.");
|
|
209472
209538
|
});
|
|
209473
|
-
addDecoder(7, () => import("./jpeg-
|
|
209474
|
-
addDecoder([8, 32946], () => import("./deflate-
|
|
209475
|
-
addDecoder(32773, () => import("./packbits-
|
|
209539
|
+
addDecoder(7, () => import("./jpeg-9VJS3-Bw.js").then((m2) => m2.default));
|
|
209540
|
+
addDecoder([8, 32946], () => import("./deflate-BnG3V84V.js").then((m2) => m2.default));
|
|
209541
|
+
addDecoder(32773, () => import("./packbits-Dm4fdK8S.js").then((m2) => m2.default));
|
|
209476
209542
|
addDecoder(
|
|
209477
209543
|
34887,
|
|
209478
|
-
() => import("./lerc-
|
|
209544
|
+
() => import("./lerc-D1J26SPX.js").then(async (m2) => {
|
|
209479
209545
|
await m2.zstd.init();
|
|
209480
209546
|
return m2;
|
|
209481
209547
|
}).then((m2) => m2.default)
|
|
209482
209548
|
);
|
|
209483
|
-
addDecoder(50001, () => import("./webimage-
|
|
209549
|
+
addDecoder(50001, () => import("./webimage-C-QWVV-f.js").then((m2) => m2.default));
|
|
209484
209550
|
function copyNewSize(array2, width2, height2, samplesPerPixel = 1) {
|
|
209485
209551
|
return new (Object.getPrototypeOf(array2)).constructor(width2 * height2 * samplesPerPixel);
|
|
209486
209552
|
}
|
|
@@ -226254,7 +226320,7 @@ class ContourLayerWithText extends ContourLayer {
|
|
|
226254
226320
|
}
|
|
226255
226321
|
ContourLayerWithText.layerName = "ContourLayerWithText";
|
|
226256
226322
|
ContourLayerWithText.defaultProps = defaultProps;
|
|
226257
|
-
const useStyles$
|
|
226323
|
+
const useStyles$u = makeStyles()(() => ({
|
|
226258
226324
|
toolButton: {
|
|
226259
226325
|
display: "inline-flex",
|
|
226260
226326
|
"&:active": {
|
|
@@ -226316,12 +226382,12 @@ const useStyles$t = makeStyles()(() => ({
|
|
|
226316
226382
|
}));
|
|
226317
226383
|
function IconTool(props) {
|
|
226318
226384
|
const { alt, onClick, isActive: isActive2, children: children3 } = props;
|
|
226319
|
-
const { classes: classes2 } = useStyles$
|
|
226385
|
+
const { classes: classes2 } = useStyles$u();
|
|
226320
226386
|
return jsx$1("button", { className: clsx(classes2.toolIcon, { [classes2.toolActive]: isActive2 }), onClick, type: "button", title: alt, children: children3 });
|
|
226321
226387
|
}
|
|
226322
226388
|
function IconButton(props) {
|
|
226323
226389
|
const { alt, onClick, children: children3 } = props;
|
|
226324
|
-
const { classes: classes2 } = useStyles$
|
|
226390
|
+
const { classes: classes2 } = useStyles$u();
|
|
226325
226391
|
return jsx$1("button", { className: clsx(classes2.toolIcon, classes2.toolButton), onClick, type: "button", title: alt, children: children3 });
|
|
226326
226392
|
}
|
|
226327
226393
|
function ToolMenu(props) {
|
|
@@ -226329,7 +226395,7 @@ function ToolMenu(props) {
|
|
|
226329
226395
|
const lassoIconAltText = "Select lasso";
|
|
226330
226396
|
const { setActiveTool, activeTool, visibleTools = { pan: true, selectLasso: true, recenter: true }, recenterOnClick = () => {
|
|
226331
226397
|
} } = props;
|
|
226332
|
-
const { classes: classes2 } = useStyles$
|
|
226398
|
+
const { classes: classes2 } = useStyles$u();
|
|
226333
226399
|
const onRecenterButtonCLick = () => {
|
|
226334
226400
|
recenterOnClick();
|
|
226335
226401
|
};
|
|
@@ -227486,7 +227552,7 @@ function ScatterplotOptions(props) {
|
|
|
227486
227552
|
id: `feature-aggregation-strategy-${scatterplotOptionsId}`
|
|
227487
227553
|
}, children: FEATURE_AGGREGATION_STRATEGIES$2.map((opt) => jsx$1("option", { value: opt, children: capitalize$3(opt) }, opt)) }) })] }) : null] });
|
|
227488
227554
|
}
|
|
227489
|
-
const useStyles$
|
|
227555
|
+
const useStyles$t = makeStyles()((theme) => ({
|
|
227490
227556
|
tooltipAnchor: {
|
|
227491
227557
|
position: "relative",
|
|
227492
227558
|
width: "0px",
|
|
@@ -227517,7 +227583,7 @@ const useStyles$s = makeStyles()((theme) => ({
|
|
|
227517
227583
|
function Tooltip3(props) {
|
|
227518
227584
|
const { x: x2, y: y2, parentWidth, parentHeight, children: children3 } = props;
|
|
227519
227585
|
const ref2 = useRef();
|
|
227520
|
-
const { classes: classes2 } = useStyles$
|
|
227586
|
+
const { classes: classes2 } = useStyles$t();
|
|
227521
227587
|
const [placementX, setPlacementX] = useState("start");
|
|
227522
227588
|
const [placementY, setPlacementY] = useState("bottom");
|
|
227523
227589
|
const getTooltipContainer = useVitessceContainer(ref2);
|
|
@@ -227533,7 +227599,7 @@ function Tooltip3(props) {
|
|
|
227533
227599
|
}, [x2, y2, parentWidth, parentHeight]);
|
|
227534
227600
|
return jsx$1("div", { ref: ref2, className: classes2.tooltipAnchor, children: ref2 && ref2.current ? jsx$1(Popper, { open: true, anchorEl: ref2.current, container: getTooltipContainer, transition: true, placement: `${placementY}-${placementX}`, children: jsx$1(Paper, { elevation: 8, className: classes2.tooltipContent, children: children3 }) }) : null });
|
|
227535
227601
|
}
|
|
227536
|
-
const useStyles$
|
|
227602
|
+
const useStyles$s = makeStyles()((theme) => ({
|
|
227537
227603
|
cellEmphasisCrosshair: {
|
|
227538
227604
|
zIndex: 50,
|
|
227539
227605
|
position: "absolute",
|
|
@@ -227544,7 +227610,7 @@ const useStyles$r = makeStyles()((theme) => ({
|
|
|
227544
227610
|
}));
|
|
227545
227611
|
function Tooltip2D(props) {
|
|
227546
227612
|
const { parentUuid, sourceUuid, x: x2, y: y2, parentWidth, parentHeight, children: children3 } = props;
|
|
227547
|
-
const { classes: classes2 } = useStyles$
|
|
227613
|
+
const { classes: classes2 } = useStyles$s();
|
|
227548
227614
|
if (x2 < 0 || x2 > parentWidth || y2 < 0 || y2 > parentHeight) {
|
|
227549
227615
|
return null;
|
|
227550
227616
|
}
|
|
@@ -231456,7 +231522,7 @@ function getXlinkHref(cmap) {
|
|
|
231456
231522
|
const xlinkHref = ramp(color2.copy().domain(quantize$3(interpolate$1$1(0, 1), n3))).toDataURL();
|
|
231457
231523
|
return xlinkHref;
|
|
231458
231524
|
}
|
|
231459
|
-
const useStyles$
|
|
231525
|
+
const useStyles$r = makeStyles()(() => ({
|
|
231460
231526
|
legend: {
|
|
231461
231527
|
position: "relative",
|
|
231462
231528
|
// Needed for absolute positioning of slider overlay
|
|
@@ -231653,7 +231719,7 @@ function Legend(props) {
|
|
|
231653
231719
|
contourThresholds
|
|
231654
231720
|
} = props;
|
|
231655
231721
|
const svgRef = useRef(null);
|
|
231656
|
-
const { classes: classes2 } = useStyles$
|
|
231722
|
+
const { classes: classes2 } = useStyles$r();
|
|
231657
231723
|
const [localRange, setLocalRange] = useState(featureValueColormapRange);
|
|
231658
231724
|
useEffect(() => {
|
|
231659
231725
|
setLocalRange(featureValueColormapRange);
|
|
@@ -231987,7 +232053,7 @@ function Legend(props) {
|
|
|
231987
232053
|
}
|
|
231988
232054
|
} })] })] });
|
|
231989
232055
|
}
|
|
231990
|
-
const useStyles$
|
|
232056
|
+
const useStyles$q = makeStyles()(() => ({
|
|
231991
232057
|
multiLegend: {
|
|
231992
232058
|
position: "absolute",
|
|
231993
232059
|
top: "0px",
|
|
@@ -232014,7 +232080,7 @@ function MultiLegend(props) {
|
|
|
232014
232080
|
pointLayerCoordination,
|
|
232015
232081
|
pointMultiIndicesData
|
|
232016
232082
|
} = props;
|
|
232017
|
-
const { classes: classes2 } = useStyles$
|
|
232083
|
+
const { classes: classes2 } = useStyles$q();
|
|
232018
232084
|
const reversedSegmentationLayerScopes = useMemo$1(() => [...segmentationLayerScopes || []].reverse(), [segmentationLayerScopes]);
|
|
232019
232085
|
const reversedSpotLayerScopes = useMemo$1(() => [...spotLayerScopes || []].reverse(), [spotLayerScopes]);
|
|
232020
232086
|
const reversedPointLayerScopes = useMemo$1(() => [...pointLayerScopes || []].reverse(), [pointLayerScopes]);
|
|
@@ -232107,7 +232173,7 @@ function MultiLegend(props) {
|
|
|
232107
232173
|
}) : null;
|
|
232108
232174
|
}) : null] });
|
|
232109
232175
|
}
|
|
232110
|
-
const useStyles$
|
|
232176
|
+
const useStyles$p = makeStyles()(() => ({
|
|
232111
232177
|
channelNamesLegendContainer: {
|
|
232112
232178
|
position: "absolute",
|
|
232113
232179
|
bottom: "0px",
|
|
@@ -232130,7 +232196,7 @@ const useStyles$o = makeStyles()(() => ({
|
|
|
232130
232196
|
}));
|
|
232131
232197
|
function ChannelNamesLegend(props) {
|
|
232132
232198
|
const { images, imageLayerScopes, imageLayerCoordination, imageChannelScopesByLayer, imageChannelCoordination } = props;
|
|
232133
|
-
const { classes: classes2 } = useStyles$
|
|
232199
|
+
const { classes: classes2 } = useStyles$p();
|
|
232134
232200
|
const reversedImageLayerScopes = useMemo$1(() => [...imageLayerScopes || []].reverse(), [imageLayerScopes]);
|
|
232135
232201
|
return jsx$1("div", { className: classes2.channelNamesLegendContainer, children: imageLayerScopes ? reversedImageLayerScopes.map((layerScope) => {
|
|
232136
232202
|
const layerCoordination = imageLayerCoordination[0][layerScope];
|
|
@@ -253674,7 +253740,7 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
|
|
|
253674
253740
|
this.viewInfoDidUpdate();
|
|
253675
253741
|
const shallowDiff2 = (propName) => prevProps[propName] !== this.props[propName];
|
|
253676
253742
|
const shallowDiffByLayer2 = (propName, scopeName) => prevProps?.[propName]?.[scopeName] !== this.props?.[propName]?.[scopeName];
|
|
253677
|
-
const
|
|
253743
|
+
const shallowDiffByChannel2 = (propName, firstName, secondName) => prevProps?.[propName]?.[firstName]?.[secondName] !== this.props?.[propName]?.[firstName]?.[secondName];
|
|
253678
253744
|
const shallowDiffByLayerCoordination = (propName, layerScope) => prevProps?.[propName]?.[0]?.[layerScope] !== this.props?.[propName]?.[0]?.[layerScope];
|
|
253679
253745
|
const shallowDiffByChannelCoordination = (propName, layerScope, channelScope) => prevProps?.[propName]?.[0]?.[layerScope]?.[channelScope] !== this.props?.[propName]?.[0]?.[layerScope]?.[channelScope];
|
|
253680
253746
|
let forceUpdate = false;
|
|
@@ -253695,7 +253761,7 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
|
|
|
253695
253761
|
} else {
|
|
253696
253762
|
this.props.segmentationLayerScopes?.forEach((layerScope) => {
|
|
253697
253763
|
this.props.segmentationChannelScopesByLayer?.[layerScope]?.forEach((channelScope) => {
|
|
253698
|
-
if (
|
|
253764
|
+
if (shallowDiffByChannel2("obsSegmentationsLocations", layerScope, channelScope)) {
|
|
253699
253765
|
this.onUpdateSegmentationsLocationsData(layerScope, channelScope);
|
|
253700
253766
|
forceUpdate = true;
|
|
253701
253767
|
}
|
|
@@ -253708,7 +253774,7 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
|
|
|
253708
253774
|
} else {
|
|
253709
253775
|
this.props.segmentationLayerScopes?.forEach((layerScope) => {
|
|
253710
253776
|
this.props.segmentationChannelScopesByLayer?.[layerScope]?.forEach((channelScope) => {
|
|
253711
|
-
if (
|
|
253777
|
+
if (shallowDiffByChannel2("obsSegmentationsSets", layerScope, channelScope) || shallowDiffByChannelCoordination("segmentationChannelCoordination", layerScope, channelScope)) {
|
|
253712
253778
|
this.onUpdateSegmentationsSetsData(layerScope, channelScope);
|
|
253713
253779
|
forceUpdate = true;
|
|
253714
253780
|
}
|
|
@@ -253721,7 +253787,7 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
|
|
|
253721
253787
|
} else {
|
|
253722
253788
|
this.props.segmentationLayerScopes?.forEach((layerScope) => {
|
|
253723
253789
|
this.props.segmentationChannelScopesByLayer?.[layerScope]?.forEach((channelScope) => {
|
|
253724
|
-
if (
|
|
253790
|
+
if (shallowDiffByChannel2("segmentationMatrixIndices", layerScope, channelScope)) {
|
|
253725
253791
|
this.onUpdateSegmentationsIndexData(layerScope, channelScope);
|
|
253726
253792
|
forceUpdate = true;
|
|
253727
253793
|
}
|
|
@@ -253734,7 +253800,7 @@ class Spatial2 extends AbstractSpatialOrScatterplot {
|
|
|
253734
253800
|
} else {
|
|
253735
253801
|
this.props.segmentationLayerScopes.forEach((layerScope) => {
|
|
253736
253802
|
this.props.segmentationChannelScopesByLayer?.[layerScope]?.forEach((channelScope) => {
|
|
253737
|
-
if (
|
|
253803
|
+
if (shallowDiffByChannel2("segmentationMatrixIndices", layerScope, channelScope) || shallowDiffByChannel2("segmentationMultiExpressionData", layerScope, channelScope)) {
|
|
253738
253804
|
this.onUpdateSegmentationsExpressionData(layerScope, channelScope);
|
|
253739
253805
|
forceUpdate = true;
|
|
253740
253806
|
}
|
|
@@ -253988,12 +254054,12 @@ class ErrorBoundary extends React__default.Component {
|
|
|
253988
254054
|
}
|
|
253989
254055
|
}
|
|
253990
254056
|
const LazySpatialThree = React__default.lazy(async () => {
|
|
253991
|
-
const { SpatialWrapper: SpatialWrapper2 } = await import("./index-
|
|
254057
|
+
const { SpatialWrapper: SpatialWrapper2 } = await import("./index-CwGBUQIk.js").then((n3) => n3.a);
|
|
253992
254058
|
return { default: SpatialWrapper2 };
|
|
253993
254059
|
});
|
|
253994
254060
|
const SpatialThreeAdapter = React__default.forwardRef((props, ref2) => jsx$1("div", { ref: ref2, style: { width: "100%", height: "100%" }, children: jsx$1(ErrorBoundary, { fallback: jsx$1("div", { children: "3D spatial view is not available in this environment." }), children: jsx$1(Suspense, { fallback: jsx$1("div", { children: "Loading..." }), children: jsx$1(LazySpatialThree, { ...props }) }) }) }));
|
|
253995
254061
|
const LazySpatialAccelerated = React__default.lazy(async () => {
|
|
253996
|
-
const { SpatialWrapper: SpatialWrapper2 } = await import("./index-
|
|
254062
|
+
const { SpatialWrapper: SpatialWrapper2 } = await import("./index-B9h9IQaz.js");
|
|
253997
254063
|
return { default: SpatialWrapper2 };
|
|
253998
254064
|
});
|
|
253999
254065
|
const SpatialAcceleratedAdapter = React__default.forwardRef((props, ref2) => jsx$1("div", { ref: ref2, style: { width: "100%", height: "100%" }, children: jsx$1(ErrorBoundary, { fallback: jsx$1("div", { children: "3D spatial view is not available in this environment." }), children: jsx$1(Suspense, { fallback: jsx$1("div", { children: "Loading..." }), children: jsx$1(LazySpatialAccelerated, { ...props }) }) }) }));
|
|
@@ -262066,7 +262132,7 @@ _defineProperty$3(WindowScroller, "defaultProps", {
|
|
|
262066
262132
|
serverHeight: 0,
|
|
262067
262133
|
serverWidth: 0
|
|
262068
262134
|
});
|
|
262069
|
-
const useStyles$
|
|
262135
|
+
const useStyles$o = makeStyles()((theme) => ({
|
|
262070
262136
|
selectableTable: {
|
|
262071
262137
|
flex: "1 1 auto",
|
|
262072
262138
|
outline: "none"
|
|
@@ -262215,7 +262281,7 @@ function SelectableTable(props) {
|
|
|
262215
262281
|
onChange(null);
|
|
262216
262282
|
}
|
|
262217
262283
|
}, [selectedRows, allowMultiple]);
|
|
262218
|
-
const { classes: classes2 } = useStyles$
|
|
262284
|
+
const { classes: classes2 } = useStyles$o();
|
|
262219
262285
|
const inputUuid = v4$1();
|
|
262220
262286
|
const rowRenderer = ({ index: index2, style: style2 }) => (
|
|
262221
262287
|
// eslint-disable-next-line jsx-a11y/interactive-supports-focus
|
|
@@ -262240,7 +262306,7 @@ const FEATURELIST_SORT_OPTIONS = [
|
|
|
262240
262306
|
"original"
|
|
262241
262307
|
];
|
|
262242
262308
|
const ALT_COLNAME = "Alternate ID";
|
|
262243
|
-
const useStyles$
|
|
262309
|
+
const useStyles$n = makeStyles()(() => ({
|
|
262244
262310
|
searchBar: {
|
|
262245
262311
|
marginTop: "10px",
|
|
262246
262312
|
marginLeft: "10px",
|
|
@@ -262253,7 +262319,7 @@ const useStyles$m = makeStyles()(() => ({
|
|
|
262253
262319
|
}));
|
|
262254
262320
|
function FeatureList(props) {
|
|
262255
262321
|
const { width: width2, height: height2, hasColorEncoding, geneList = [], featureLabelsMap, geneSelection = [], geneFilter = null, setGeneSelection, enableMultiSelect, showFeatureTable, featureListSort, featureListSortKey, hasFeatureLabels, primaryColumnName } = props;
|
|
262256
|
-
const { classes: classes2 } = useStyles$
|
|
262322
|
+
const { classes: classes2 } = useStyles$n();
|
|
262257
262323
|
const [searchTerm, setSearchTerm] = useState("");
|
|
262258
262324
|
const selectableTableSortKey = featureListSortKey === "featureIndex" ? "key" : "name";
|
|
262259
262325
|
const searchResults = useMemo$1(() => geneList.filter((gene) => gene.toLowerCase().includes(searchTerm.toLowerCase()) || featureLabelsMap?.get(gene)?.toLowerCase().includes(searchTerm.toLowerCase()) || featureLabelsMap?.get(cleanFeatureId(gene))?.toLowerCase().includes(searchTerm.toLowerCase())), [geneList, searchTerm, featureLabelsMap]);
|
|
@@ -262326,7 +262392,7 @@ function FeatureListOptions(props) {
|
|
|
262326
262392
|
id: `feature-list-show-alternative-ids-${featureListId}`
|
|
262327
262393
|
} } }) })] })] }) : null] });
|
|
262328
262394
|
}
|
|
262329
|
-
const useStyles$
|
|
262395
|
+
const useStyles$m = makeStyles()((theme) => ({
|
|
262330
262396
|
featureListContainer: {
|
|
262331
262397
|
width: "100%",
|
|
262332
262398
|
height: "100%",
|
|
@@ -262341,7 +262407,7 @@ function FeatureListSubscriber(props) {
|
|
|
262341
262407
|
const loaders = useLoaders();
|
|
262342
262408
|
const coordinationScopes = useCoordinationScopes(coordinationScopesRaw);
|
|
262343
262409
|
const [width2, height2, containerRef] = useGridItemSize();
|
|
262344
|
-
const { classes: classes2 } = useStyles$
|
|
262410
|
+
const { classes: classes2 } = useStyles$m();
|
|
262345
262411
|
const [{ dataset, obsType, featureType, featureSelection: geneSelection, featureFilter: geneFilter, obsColorEncoding: cellColorEncoding }, { setFeatureSelection: setGeneSelection, setFeatureFilter: setGeneFilter, setFeatureHighlight: setGeneHighlight, setObsColorEncoding: setCellColorEncoding }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType$1.FEATURE_LIST], coordinationScopes);
|
|
262346
262412
|
const variablesLabel = variablesLabelOverride || featureType;
|
|
262347
262413
|
const title2 = titleOverride || `${capitalize$3(variablesLabel)} List`;
|
|
@@ -262476,7 +262542,7 @@ const useSelectionSliderStyles = makeStyles()(() => ({
|
|
|
262476
262542
|
backgroundColor: "rgba(128, 128, 128, 0.7)"
|
|
262477
262543
|
}
|
|
262478
262544
|
}));
|
|
262479
|
-
const useStyles$
|
|
262545
|
+
const useStyles$l = makeStyles()((theme) => ({
|
|
262480
262546
|
paletteContainer: {
|
|
262481
262547
|
width: "70px",
|
|
262482
262548
|
height: "40px",
|
|
@@ -262497,10 +262563,10 @@ const useStyles$k = makeStyles()((theme) => ({
|
|
|
262497
262563
|
}
|
|
262498
262564
|
}));
|
|
262499
262565
|
const ColorPalette = ({ handleChange }) => {
|
|
262500
|
-
const { classes: classes2 } = useStyles$
|
|
262566
|
+
const { classes: classes2 } = useStyles$l();
|
|
262501
262567
|
return jsx$1("div", { className: classes2.paletteContainer, "aria-label": "Color swatch", children: VIEWER_PALETTE.map((color2) => jsx$1(IconButton$1, { className: classes2.button, onClick: () => handleChange(color2), "aria-label": `Change color to ${color2}`, children: jsx$1(LensIcon, { fontSize: "small", style: { color: `rgb(${color2})` }, className: classes2.icon }) }, color2)) });
|
|
262502
262568
|
};
|
|
262503
|
-
const useStyles$
|
|
262569
|
+
const useStyles$k = makeStyles()(() => ({
|
|
262504
262570
|
menuButton: {
|
|
262505
262571
|
backgroundColor: "transparent"
|
|
262506
262572
|
},
|
|
@@ -262519,7 +262585,7 @@ function MuiSpan(props) {
|
|
|
262519
262585
|
}
|
|
262520
262586
|
function ChannelOptions$1({ handlePropertyChange, handleChannelRemove, handleIQRUpdate }) {
|
|
262521
262587
|
const [open2, setOpen] = useState(false);
|
|
262522
|
-
const { classes: classes2 } = useStyles$
|
|
262588
|
+
const { classes: classes2 } = useStyles$k();
|
|
262523
262589
|
const handleColorSelect = (color2) => {
|
|
262524
262590
|
handlePropertyChange("color", color2);
|
|
262525
262591
|
};
|
|
@@ -263136,7 +263202,7 @@ function LayerController$1(props) {
|
|
|
263136
263202
|
minWidth: "50%"
|
|
263137
263203
|
} })] }), jsx$1(TabPanel, { value: tab2, index: 0, children: FullController }), jsx$1(TabPanel, { value: tab2, index: 1, style: { marginTop: 4 }, children: jsx$1(VolumeOptions, { loader: loader2, handleSlicerSetting, handleRenderingModeChange: setRenderingMode, renderingMode, xSlice, ySlice, zSlice, use3d, setViewState, spatialHeight, spatialWidth, modelMatrix: modelMatrix2 }) })] }) : FullController, shouldShowRemoveLayerButton ? jsx$1(Button, { onClick: handleLayerRemove, fullWidth: true, variant: "outlined", style: buttonStyles, size: "small", children: "Remove Image Layer" }) : null] })] });
|
|
263138
263204
|
}
|
|
263139
|
-
const useStyles$
|
|
263205
|
+
const useStyles$j = makeStyles()(() => ({
|
|
263140
263206
|
addButton: {
|
|
263141
263207
|
marginTop: "10px",
|
|
263142
263208
|
marginBottom: "10px",
|
|
@@ -263148,7 +263214,7 @@ function ImageAddIcon() {
|
|
|
263148
263214
|
}
|
|
263149
263215
|
function ImageAddButton({ imageOptions, handleImageAdd }) {
|
|
263150
263216
|
const [open2, setOpen] = useState(false);
|
|
263151
|
-
const { classes: classes2 } = useStyles$
|
|
263217
|
+
const { classes: classes2 } = useStyles$j();
|
|
263152
263218
|
const handleAdd = (imgData) => {
|
|
263153
263219
|
setOpen((prev2) => !prev2);
|
|
263154
263220
|
handleImageAdd(imgData);
|
|
@@ -263480,7 +263546,7 @@ const useEllipsisMenuStyles = makeStyles()(() => ({
|
|
|
263480
263546
|
padding: "4px"
|
|
263481
263547
|
}
|
|
263482
263548
|
}));
|
|
263483
|
-
const useStyles$
|
|
263549
|
+
const useStyles$i = makeStyles()(() => ({
|
|
263484
263550
|
colorPickerPaper: {
|
|
263485
263551
|
overflow: "hidden",
|
|
263486
263552
|
"& > ul": {
|
|
@@ -263538,7 +263604,7 @@ function ChannelColorPickerMenu(props) {
|
|
|
263538
263604
|
setColor2([rgb2.r, rgb2.g, rgb2.b]);
|
|
263539
263605
|
}
|
|
263540
263606
|
}
|
|
263541
|
-
const { classes: classes2 } = useStyles$
|
|
263607
|
+
const { classes: classes2 } = useStyles$i();
|
|
263542
263608
|
const currentColor = color2 ? colorArrayToString(color2) : colorArrayToString(getDefaultColor(theme));
|
|
263543
263609
|
const isWritable = typeof setColor2 === "function";
|
|
263544
263610
|
const derivedOpen = isWritable ? isStaticColor && visible ? open2 : false : false;
|
|
@@ -263546,7 +263612,7 @@ function ChannelColorPickerMenu(props) {
|
|
|
263546
263612
|
[classes2.colorIconOutline]: theme !== "dark" && isEqual$3(color2, [255, 255, 255])
|
|
263547
263613
|
}), style: { backgroundColor: currentColor } }) : isColormap && visible && featureValueColormap ? jsx$1("div", { className: classes2.colorIcon, children: jsx$1("svg", { width: "18", height: "18", children: jsx$1("image", { x: 0, y: 0, width: 18, height: 18, preserveAspectRatio: "none", href: getXlinkHref(featureValueColormap), clipPath: "inset(0% round 4px)" }) }) }) : jsx$1("div", { className: classes2.colorIcon }), buttonClassName: classes2.colorIconButton, withPaper: true, paperClassName: classes2.colorPickerPaper, "aria-label": "Open color picker menu", children: jsx$1(Twitter$1, { className: classes2.colorPicker, disableAlpha: true, width: 108, triangle: "hide", colors: defaultPalette, color: currentColor, onChangeComplete: handleColorChange }) });
|
|
263548
263614
|
}
|
|
263549
|
-
const useStyles$
|
|
263615
|
+
const useStyles$h = makeStyles()(() => ({
|
|
263550
263616
|
layerTypeSpotIcon: {
|
|
263551
263617
|
height: "100%",
|
|
263552
263618
|
marginLeft: "1px",
|
|
@@ -263559,7 +263625,7 @@ const useStyles$g = makeStyles()(() => ({
|
|
|
263559
263625
|
function SpotLayerEllipsisMenu(props) {
|
|
263560
263626
|
const { strokeWidth, setStrokeWidth, filled, setFilled, featureSelection, obsColorEncoding, setObsColorEncoding, featureValueColormap, setFeatureValueColormap, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible } = props;
|
|
263561
263627
|
const [open2, setOpen] = useState(false);
|
|
263562
|
-
const { classes: classes2 } = useStyles$
|
|
263628
|
+
const { classes: classes2 } = useStyles$h();
|
|
263563
263629
|
const { classes: selectClasses2 } = useSelectStyles();
|
|
263564
263630
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
263565
263631
|
const filledId = $bdb11010cef70236$export$f680877a34711e37();
|
|
@@ -263581,7 +263647,7 @@ function SpotLayerController(props) {
|
|
|
263581
263647
|
const Visibility = useMemo$1(() => visibleSetting ? VisibilityIcon : VisibilityOffIcon, [visibleSetting]);
|
|
263582
263648
|
const isStaticColor = obsColorEncoding === "spatialLayerColor";
|
|
263583
263649
|
const isColormap = obsColorEncoding === "geneSelection";
|
|
263584
|
-
const { classes: classes2 } = useStyles$
|
|
263650
|
+
const { classes: classes2 } = useStyles$h();
|
|
263585
263651
|
const { classes: lcClasses } = useControllerSectionStyles();
|
|
263586
263652
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
263587
263653
|
const handleVisibleChange = useCallback(() => {
|
|
@@ -263591,7 +263657,7 @@ function SpotLayerController(props) {
|
|
|
263591
263657
|
const handleOpacityChange = useCallback((e3, v) => setOpacity2(v), [setOpacity2]);
|
|
263592
263658
|
return jsx$1(Grid$1, { className: lcClasses.layerControllerGrid, children: jsx$1(Paper, { elevation: 4, className: lcClasses.layerControllerRoot, children: jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsx$1(Grid$1, { size: 1, children: jsx$1(Button, { onClick: handleVisibleChange, className: menuClasses.imageLayerVisibleButton, "aria-label": "Toggle spot layer visibility", children: jsx$1(Visibility, {}) }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(ChannelColorPickerMenu, { theme, color: color2, setColor: setColor2, palette, isStaticColor, isColormap, featureValueColormap, visible }) }), jsx$1(Grid$1, { size: 6, children: jsx$1(Typography, { className: menuClasses.imageLayerName, children: label2 }) }), jsx$1(Grid$1, { size: 2, children: jsx$1(Slider, { value: opacity2, min: 0, max: 1, step: 1e-3, onChange: handleOpacityChange, className: menuClasses.imageLayerOpacitySlider, orientation: "horizontal", "aria-label": `Adjust opacity for layer ${label2}` }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(SpotLayerEllipsisMenu, { filled, setFilled, strokeWidth, setStrokeWidth, featureSelection, obsColorEncoding, setObsColorEncoding, featureValueColormap, setFeatureValueColormap, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(SvgSpots, { className: classes2.layerTypeSpotIcon }) })] }) }) });
|
|
263593
263659
|
}
|
|
263594
|
-
const useStyles$
|
|
263660
|
+
const useStyles$g = makeStyles()(() => ({
|
|
263595
263661
|
layerFeatureControllerGrid: {
|
|
263596
263662
|
padding: "0",
|
|
263597
263663
|
flexWrap: "nowrap"
|
|
@@ -263636,14 +263702,15 @@ function LayerPerFeatureController(props) {
|
|
|
263636
263702
|
]);
|
|
263637
263703
|
}
|
|
263638
263704
|
}, [featureName, featureColor, setFeatureColor, featureColorIndex]);
|
|
263639
|
-
const { classes: classes2 } = useStyles$
|
|
263705
|
+
const { classes: classes2 } = useStyles$g();
|
|
263640
263706
|
const { classes: lcClasses } = useControllerSectionStyles();
|
|
263641
263707
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
263642
263708
|
const [open2, setOpen] = useState(false);
|
|
263643
263709
|
const { colorPickerColor, colorPickerReadable, colorPickerWritable, colorPickerTooltip } = useMemo$1(() => {
|
|
263644
263710
|
if (obsColorEncoding === "geneSelection") {
|
|
263711
|
+
const storedColor = featureColor?.find((fc) => fc.name === featureName)?.color;
|
|
263645
263712
|
return {
|
|
263646
|
-
colorPickerColor:
|
|
263713
|
+
colorPickerColor: storedColor ?? randomByFeatureColor ?? spatialLayerColor,
|
|
263647
263714
|
colorPickerReadable: true,
|
|
263648
263715
|
colorPickerWritable: true,
|
|
263649
263716
|
colorPickerTooltip: null
|
|
@@ -263689,7 +263756,7 @@ function LayerPerFeatureController(props) {
|
|
|
263689
263756
|
]);
|
|
263690
263757
|
return jsx$1(Grid$1, { className: lcClasses.layerControllerGrid, children: jsxs(Paper, { elevation: 2, className: lcClasses.layerControllerSubRow, children: [jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsx$1(Grid$1, { size: 1, children: jsx$1(Button, { onClick: handleRemoveFeature, className: menuClasses.imageLayerVisibleButton, "aria-label": "Remove feature", children: jsx$1(ClearIcon, {}) }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(Tooltip$3, { title: colorPickerTooltip ?? "", disableHoverListener: !colorPickerTooltip, placement: "top", children: jsx$1("span", { children: jsx$1(ChannelColorPickerMenu, { theme, color: colorPickerColor, setColor: colorPickerWritable ? handleColorChange : null, palette, isStaticColor: colorPickerReadable, isColormap: false, featureValueColormap, visible: true }) }) }) }), jsx$1(Grid$1, { size: 6, children: jsx$1(Typography, { className: menuClasses.imageLayerName, children: featureName }) }), jsx$1(Grid$1, { size: 2, sx: { paddingRight: "12px", overflow: "visible" }, children: jsx$1(Slider, { value: opacity2, min: 0, max: 1, step: 1e-3, onChange: handleOpacityChange, className: menuClasses.imageLayerOpacitySlider, orientation: "horizontal", "aria-label": `Adjust opacity for layer ${featureName}` }) }), jsxs(Grid$1, { size: 1, container: true, direction: "row", children: [jsx$1(SvgPoints, { className: classes2.layerTypeFeatureIcon }), null] })] }), loadingDoneFraction < 1 ? jsx$1(Grid$1, { size: 12, container: true, direction: "column", justifyContent: "space-between", className: classes2.layerFeatureControllerGrid, children: jsx$1(LinearProgress, { variant: loadingDoneFraction === 0 ? "indeterminate" : "determinate", value: loadingDoneFraction * 100 }) }) : null] }) }, featureName);
|
|
263691
263758
|
}
|
|
263692
|
-
const useStyles$
|
|
263759
|
+
const useStyles$f = makeStyles()(() => ({
|
|
263693
263760
|
pointLayerButton: {
|
|
263694
263761
|
borderStyle: "dashed",
|
|
263695
263762
|
marginTop: "10px",
|
|
@@ -263718,7 +263785,7 @@ const useStyles$e = makeStyles()(() => ({
|
|
|
263718
263785
|
}
|
|
263719
263786
|
}));
|
|
263720
263787
|
function PointLayerEllipsisMenu(props) {
|
|
263721
|
-
const { featureSelection, featureFilterMode, setFeatureFilterMode, obsColorEncoding, setObsColorEncoding, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible } = props;
|
|
263788
|
+
const { featureSelection, featureFilterMode, setFeatureFilterMode, obsColorEncoding, setObsColorEncoding, featureValueColormap, setFeatureValueColormap, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible } = props;
|
|
263722
263789
|
const [open2, setOpen] = useState(false);
|
|
263723
263790
|
const { classes: selectClasses2 } = useSelectStyles();
|
|
263724
263791
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
@@ -263728,7 +263795,8 @@ function PointLayerEllipsisMenu(props) {
|
|
|
263728
263795
|
const crosshairsVisibleId = $bdb11010cef70236$export$f680877a34711e37();
|
|
263729
263796
|
const legendVisibleId = $bdb11010cef70236$export$f680877a34711e37();
|
|
263730
263797
|
const featureFilterModeId = $bdb11010cef70236$export$f680877a34711e37();
|
|
263731
|
-
|
|
263798
|
+
const colormapSelectorId = $bdb11010cef70236$export$f680877a34711e37();
|
|
263799
|
+
return jsxs(PopperMenu, { open: open2, setOpen, buttonIcon: jsx$1(MoreVertIcon, {}), buttonClassName: menuClasses.imageLayerMenuButton, containerClassName: menuClasses.imageLayerPopperContainer, withPaper: true, getAriaLabel: () => "Open point layer options menu", children: [jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: colormapSelectorId, children: "Colormap: " }), jsx$1(NativeSelect, { onChange: (e3) => setFeatureValueColormap(e3.target.value), value: featureValueColormap, inputProps: { id: colormapSelectorId, "aria-label": "Colormap selector" }, classes: { root: selectClasses2.selectRoot }, children: GLSL_COLORMAPS.map((cmap) => jsx$1("option", { value: cmap, children: cmap }, cmap)) })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: quantitativeColormapId, children: "Color Encoding: " }), jsxs(NativeSelect, { onChange: (e3) => setObsColorEncoding(e3.target.value), value: obsColorEncoding, inputProps: { id: quantitativeColormapId, "aria-label": "Color encoding selector" }, classes: { root: selectClasses2.selectRoot }, children: [jsx$1("option", { value: "spatialLayerColor", children: "Static Color" }), jsx$1("option", { value: "geneSelection", children: "Feature Color" }), jsx$1("option", { value: "randomByFeature", children: "Random Color per Feature" }), jsx$1("option", { value: "random", children: "Random Color per Point" })] })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: featureFilterModeId, children: "Filter to Feature Selection: " }), jsx$1(Checkbox$1, { color: "primary", className: menuClasses.menuItemCheckbox, checked: featureFilterMode === "featureSelection", onChange: (e3, v) => setFeatureFilterMode(v ? "featureSelection" : null), slotProps: { input: { id: featureFilterModeId, "aria-label": "Toggle feature filter mode" } } })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: colormapRangeId, children: "Colormap Range: " }), jsx$1(Slider, { disabled: obsColorEncoding !== "geneSelection", value: featureValueColormapRange, min: 0, max: 1, step: 0.01, onChange: (e3, v) => setFeatureValueColormapRange(v), className: menuClasses.menuItemSlider, orientation: "horizontal", id: colormapRangeId, getAriaLabel: (index2) => index2 === 0 ? "Low value colormap range slider" : "High value colormap range slider" })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: tooltipsVisibleId, children: "Tooltips Visible: " }), jsx$1(Checkbox$1, { color: "primary", className: menuClasses.menuItemCheckbox, checked: tooltipsVisible, onChange: (e3, v) => setTooltipsVisible(v), slotProps: { input: { id: tooltipsVisibleId, "aria-label": "Toggle tooltip visibility" } } })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: crosshairsVisibleId, children: "Tooltip Crosshairs Visible: " }), jsx$1(Checkbox$1, { color: "primary", className: menuClasses.menuItemCheckbox, checked: tooltipCrosshairsVisible, onChange: (e3, v) => setTooltipCrosshairsVisible(v), slotProps: { input: { id: crosshairsVisibleId, "aria-label": "Toggle tooltip crosshair visibility" } } })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: legendVisibleId, children: "Legend Visible: " }), jsx$1(Checkbox$1, { color: "primary", className: menuClasses.menuItemCheckbox, checked: legendVisible, onChange: (e3, v) => setLegendVisible(v), slotProps: { input: { id: legendVisibleId, "aria-label": "Toggle legend visibility" } } })] })] });
|
|
263732
263800
|
}
|
|
263733
263801
|
function PointLayerController(props) {
|
|
263734
263802
|
const { theme, layerScope, layerCoordination, setLayerCoordination, palette = null, pointMatrixIndicesData, tiledPointsLoadingProgress, layerPerFeatureForPoints } = props;
|
|
@@ -263758,7 +263826,7 @@ function PointLayerController(props) {
|
|
|
263758
263826
|
}, [featureColor, featureSelection]);
|
|
263759
263827
|
const isStaticColor = obsColorEncoding === "spatialLayerColor" || obsColorEncoding === "geneSelection";
|
|
263760
263828
|
const showStaticColor = obsColorEncoding === "spatialLayerColor" || obsColorEncoding === "geneSelection" && hasUnspecifiedFeatureColors;
|
|
263761
|
-
const isColormap =
|
|
263829
|
+
const isColormap = obsColorEncoding === "geneSelection";
|
|
263762
263830
|
const hasSingleSelectedFeature = obsColorEncoding === "geneSelection" && Array.isArray(featureSelection) && featureSelection.length === 1;
|
|
263763
263831
|
const color2 = useMemo$1(() => {
|
|
263764
263832
|
if (showStaticColor) {
|
|
@@ -263805,7 +263873,7 @@ function PointLayerController(props) {
|
|
|
263805
263873
|
featureSelection,
|
|
263806
263874
|
showStaticColor
|
|
263807
263875
|
]);
|
|
263808
|
-
const { classes: classes2 } = useStyles$
|
|
263876
|
+
const { classes: classes2 } = useStyles$f();
|
|
263809
263877
|
const { classes: lcClasses } = useControllerSectionStyles();
|
|
263810
263878
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
263811
263879
|
const handleVisibleChange = useCallback(() => {
|
|
@@ -263817,9 +263885,24 @@ function PointLayerController(props) {
|
|
|
263817
263885
|
const [coloringTabIndex, setColoringTabIndex] = useState(0);
|
|
263818
263886
|
const { featureIndex } = pointMatrixIndicesData || {};
|
|
263819
263887
|
const hasSelectedFeatures = Array.isArray(featureSelection) && featureSelection.length > 0;
|
|
263820
|
-
|
|
263888
|
+
useEffect(() => {
|
|
263889
|
+
if (obsColorEncoding !== "geneSelection" || !Array.isArray(featureSelection))
|
|
263890
|
+
return;
|
|
263891
|
+
const cleanedFeatureColor = (featureColor ?? []).filter((fc) => featureSelection.includes(fc.name));
|
|
263892
|
+
const missingEntries = featureSelection.filter((featureName) => !cleanedFeatureColor.find((fc) => fc.name === featureName)).map((featureName) => {
|
|
263893
|
+
const varIdx = featureIndex?.indexOf(featureName) ?? -1;
|
|
263894
|
+
const fColor = varIdx >= 0 ? PALETTE[varIdx % PALETTE.length] : getDefaultColor(theme);
|
|
263895
|
+
return { name: featureName, color: fColor };
|
|
263896
|
+
});
|
|
263897
|
+
const nextFeatureColor = [...cleanedFeatureColor, ...missingEntries];
|
|
263898
|
+
const changed = nextFeatureColor.length !== featureColor?.length || missingEntries.length > 0;
|
|
263899
|
+
if (changed) {
|
|
263900
|
+
setFeatureColor(nextFeatureColor);
|
|
263901
|
+
}
|
|
263902
|
+
}, [featureSelection, obsColorEncoding, featureIndex, featureColor]);
|
|
263903
|
+
return jsxs(Grid$1, { className: lcClasses.layerControllerGrid, children: [jsxs(Paper, { elevation: 4, className: lcClasses.layerControllerRoot, children: [jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsx$1(Grid$1, { size: 1, children: jsx$1(Button, { onClick: handleVisibleChange, className: menuClasses.imageLayerVisibleButton, "aria-label": "Toggle layer visibility", children: jsx$1(Visibility, {}) }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(ChannelColorPickerMenu, { theme, color: color2, setColor: setColor2, palette, isStaticColor, isColormap, featureValueColormap, visible }) }), jsx$1(Grid$1, { size: 6, children: jsx$1(Typography, { className: menuClasses.imageLayerName, children: label2 }) }), jsx$1(Grid$1, { size: 2, children: jsx$1(Slider, { value: opacity2, min: 0, max: 1, step: 1e-3, onChange: handleOpacityChange, className: menuClasses.imageLayerOpacitySlider, orientation: "horizontal", "aria-label": `Adjust opacity for layer ${label2}` }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(PointLayerEllipsisMenu, { featureSelection, obsColorEncoding, setObsColorEncoding, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible, featureFilterMode, setFeatureFilterMode, featureValueColormap, setFeatureValueColormap }) }), jsxs(Grid$1, { size: 1, container: true, direction: "row", children: [jsx$1(SvgPoints, { className: classes2.layerTypePointIcon }), null] })] }), loadingDoneFraction < 1 ? jsx$1(Grid$1, { size: 12, container: true, direction: "column", justifyContent: "space-between", className: classes2.pointFeatureControllerGrid, children: jsx$1(LinearProgress, { variant: loadingDoneFraction === 0 ? "indeterminate" : "determinate", value: loadingDoneFraction * 100 }) }) : null, null] }), layerPerFeatureForPoints && hasSelectedFeatures ? jsxs(Fragment, { children: [featureSelection.map((featureName) => jsx$1(LayerPerFeatureController, { theme, featureName, featureColor, setFeatureColor, spatialLayerColor, featureIndex, featureValueColormap, featureSelection, setFeatureSelection, obsColorEncoding, loadingDoneFraction, opacity: opacity2, handleOpacityChange }, featureName)), jsx$1(Grid$1, { className: lcClasses.layerControllerGrid, children: jsx$1(Paper, { elevation: 2, className: lcClasses.layerControllerSubRow, children: jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsx$1(Grid$1, { size: 1, children: jsx$1(Button, { onClick: () => setFeatureFilterMode(featureFilterMode === "featureSelection" ? null : "featureSelection"), className: menuClasses.imageLayerVisibleButton, "aria-label": "Toggle visibility of unselected points", children: featureFilterMode === "featureSelection" ? jsx$1(VisibilityOffIcon, {}) : jsx$1(VisibilityIcon, {}) }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(ChannelColorPickerMenu, { theme, color: getDefaultColor("dark"), setColor: null, isStaticColor: true, isColormap: false, visible: true }) }), jsx$1(Grid$1, { size: 6, children: jsx$1(Typography, { className: menuClasses.imageLayerName, children: "Unselected" }) }), jsx$1(Grid$1, { size: 2, sx: { paddingRight: "12px", overflow: "visible" }, children: jsx$1(Slider, { value: opacity2, min: 0, max: 1, step: 1e-3, onChange: handleOpacityChange, className: menuClasses.imageLayerOpacitySlider, orientation: "horizontal", "aria-label": "Adjust opacity for unselected layer" }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(SvgPoints, { className: classes2.layerTypePointIcon }) })] }) }) })] }) : null] });
|
|
263821
263904
|
}
|
|
263822
|
-
const useStyles$
|
|
263905
|
+
const useStyles$e = makeStyles()(() => ({
|
|
263823
263906
|
layerTypeSegmentationIcon: {
|
|
263824
263907
|
height: "100%",
|
|
263825
263908
|
marginLeft: "1px",
|
|
@@ -263832,7 +263915,7 @@ const useStyles$d = makeStyles()(() => ({
|
|
|
263832
263915
|
function SegmentationChannelEllipsisMenu(props) {
|
|
263833
263916
|
const { obsType, featureType, featureValueType, strokeWidth, setStrokeWidth, filled, setFilled, featureSelection, obsColorEncoding, setObsColorEncoding, featureValueColormap, setFeatureValueColormap, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible } = props;
|
|
263834
263917
|
const [open2, setOpen] = useState(false);
|
|
263835
|
-
const { classes: classes2 } = useStyles$
|
|
263918
|
+
const { classes: classes2 } = useStyles$e();
|
|
263836
263919
|
const { classes: selectClasses2 } = useSelectStyles();
|
|
263837
263920
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
263838
263921
|
const filledId = $bdb11010cef70236$export$f680877a34711e37();
|
|
@@ -263851,7 +263934,7 @@ function SegmentationChannelController(props) {
|
|
|
263851
263934
|
const Visibility = useMemo$1(() => visibleSetting ? VisibilityIcon : VisibilityOffIcon, [visibleSetting]);
|
|
263852
263935
|
const isStaticColor = obsColorEncoding === "spatialChannelColor";
|
|
263853
263936
|
const isColormap = obsColorEncoding === "geneSelection";
|
|
263854
|
-
const { classes: classes2 } = useStyles$
|
|
263937
|
+
const { classes: classes2 } = useStyles$e();
|
|
263855
263938
|
const { classes: lcClasses } = useControllerSectionStyles();
|
|
263856
263939
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
263857
263940
|
const handleVisibleChange = useCallback(() => {
|
|
@@ -265092,7 +265175,7 @@ function useBaseQuery(options, Observer, queryClient) {
|
|
|
265092
265175
|
function useQuery(options, queryClient) {
|
|
265093
265176
|
return useBaseQuery(options, QueryObserver);
|
|
265094
265177
|
}
|
|
265095
|
-
const useStyles$
|
|
265178
|
+
const useStyles$d = makeStyles()(() => ({
|
|
265096
265179
|
channelMenuButton: {
|
|
265097
265180
|
backgroundColor: "transparent",
|
|
265098
265181
|
padding: "3px 0",
|
|
@@ -265106,7 +265189,7 @@ const useStyles$c = makeStyles()(() => ({
|
|
|
265106
265189
|
function ChannelOptions(props) {
|
|
265107
265190
|
const { onRemove: onRemove2, onResetWindowUsingIQR, showValueExtent, setShowValueExtent, numResolutions, spatialMaxResolution, setSpatialMaxResolution } = props;
|
|
265108
265191
|
const [open2, setOpen] = useState(false);
|
|
265109
|
-
const { classes: classes2 } = useStyles$
|
|
265192
|
+
const { classes: classes2 } = useStyles$d();
|
|
265110
265193
|
const { classes: selectClasses2 } = useSelectStyles();
|
|
265111
265194
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
265112
265195
|
function handleRemove() {
|
|
@@ -265119,7 +265202,7 @@ function ChannelOptions(props) {
|
|
|
265119
265202
|
const domainTypeId = $bdb11010cef70236$export$f680877a34711e37();
|
|
265120
265203
|
return jsxs(PopperMenu, { open: open2, setOpen, buttonIcon: jsx$1(MoreVertIcon, { fontSize: "small" }), buttonClassName: classes2.channelMenuButton, containerClassName: menuClasses.imageLayerPopperContainer, placement: "bottom-end", withPaper: true, "aria-label": "Open channel options menu", children: [jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: domainTypeId, children: "Best Resolution: " }), jsx$1(Slider, { value: spatialMaxResolution || 1, valueLabelDisplay: "auto", onChange: (e3, v) => setSpatialMaxResolution(v), min: 1, max: numResolutions - 1, step: 1, orientation: "horizontal" })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: domainTypeId, children: "Slider Extent: " }), jsxs(NativeSelect, { onChange: handleDomainTypeChange, value: showValueExtent ? "Value Min/Max" : "Dtype Min/Max", inputProps: { id: domainTypeId, "aria-label": "Slider extent selector" }, classes: { root: selectClasses2.selectRoot }, children: [jsx$1("option", { value: "Value Min/Max", children: "Value Min/Max" }), jsx$1("option", { value: "Dtype Min/Max", children: "Dtype Min/Max" })] })] }), jsx$1(MenuItem, { dense: true, disableGutters: true, component: "button", onClick: onResetWindowUsingIQR, className: classes2.menuItemButton, "aria-label": "Click to use IQR for channel", children: "Reset window using IQR" }), jsx$1(MenuItem, { dense: true, disableGutters: true, component: "button", onClick: handleRemove, className: classes2.menuItemButton, "aria-label": "Click to remove channel", children: "Remove channel" })] });
|
|
265121
265204
|
}
|
|
265122
|
-
const useStyles$
|
|
265205
|
+
const useStyles$c = makeStyles()(() => ({
|
|
265123
265206
|
channelSlider: {
|
|
265124
265207
|
marginTop: "7px"
|
|
265125
265208
|
}
|
|
@@ -265129,7 +265212,7 @@ function ChannelSlider(props) {
|
|
|
265129
265212
|
const rgbColor = toRgbUIString(colormapOn, color2, theme);
|
|
265130
265213
|
const dtype = image2?.getDtype();
|
|
265131
265214
|
const fullDomain = dtype ? DOMAINS[dtype] : [0, 0];
|
|
265132
|
-
const { classes: classes2 } = useStyles$
|
|
265215
|
+
const { classes: classes2 } = useStyles$c();
|
|
265133
265216
|
useEffect(() => {
|
|
265134
265217
|
if (!window2 && !disabled && Array.isArray(minMaxDomain)) {
|
|
265135
265218
|
setWindow2(minMaxDomain);
|
|
@@ -265144,7 +265227,7 @@ function ChannelSlider(props) {
|
|
|
265144
265227
|
return `${labelPrefix} for ${rgbColor} colormap channel`;
|
|
265145
265228
|
}, getAriaValueText: () => `Current colormap values: ${rgbColor}-${window2}`, min: min2, max: max2, step, orientation: "horizontal", className: classes2.channelSlider, style: { color: rgbColor }, disabled });
|
|
265146
265229
|
}
|
|
265147
|
-
const useStyles$
|
|
265230
|
+
const useStyles$b = makeStyles()(() => ({
|
|
265148
265231
|
visibilityCheckbox: {
|
|
265149
265232
|
padding: "10px 0"
|
|
265150
265233
|
}
|
|
@@ -265158,10 +265241,10 @@ function getCheckboxColor(colormapOn, color2, theme) {
|
|
|
265158
265241
|
function ChannelVisibilityCheckbox(props) {
|
|
265159
265242
|
const { color: color2, visible, setVisible, disabled, theme, colormapOn } = props;
|
|
265160
265243
|
const rgbColor = getCheckboxColor(colormapOn, color2, theme);
|
|
265161
|
-
const { classes: classes2 } = useStyles$
|
|
265244
|
+
const { classes: classes2 } = useStyles$b();
|
|
265162
265245
|
return jsx$1(Checkbox$1, { onChange: (e3, v) => setVisible(v), checked: visible, disabled, className: classes2.visibilityCheckbox, style: { color: rgbColor, "&$checked": { color: rgbColor } }, slotProps: { input: { "aria-label": "Toggle channel visibility" } } });
|
|
265163
265246
|
}
|
|
265164
|
-
const useStyles$
|
|
265247
|
+
const useStyles$a = makeStyles()(() => ({
|
|
265165
265248
|
oneLineChannelSelect: {
|
|
265166
265249
|
width: "90%",
|
|
265167
265250
|
marginLeft: "5%",
|
|
@@ -265170,7 +265253,7 @@ const useStyles$9 = makeStyles()(() => ({
|
|
|
265170
265253
|
}));
|
|
265171
265254
|
function ChannelSelectionDropdown(props) {
|
|
265172
265255
|
const { featureIndex, channelsSortOrder, targetC, setTargetC, setWindow: setWindow2, disabled } = props;
|
|
265173
|
-
const { classes: classes2 } = useStyles$
|
|
265256
|
+
const { classes: classes2 } = useStyles$a();
|
|
265174
265257
|
const { classes: selectClasses2 } = useSelectStyles();
|
|
265175
265258
|
function handleChange(event2) {
|
|
265176
265259
|
setTargetC(event2.target.value === "" ? null : Number(event2.target.value));
|
|
@@ -265305,7 +265388,7 @@ function LoadingStatusIndicator(props) {
|
|
|
265305
265388
|
}
|
|
265306
265389
|
return jsxs(Grid$1, { container: true, px: 0.5, children: [jsx$1(Grid$1, { size: 6, alignItems: "start", children: jsx$1(Grid$1, { container: true, alignItems: "center", gap: 1, children: statusColor !== "success" ? jsx$1(StatusChip, { label: statusLabel, color: statusColor, size: "small" }) : null }) }), jsx$1(Grid$1, { size: 6, px: 1, my: 0.25, children: jsx$1(LoadingText, { bricksLoaded, currentRequestCount, totalBricksRequested, isLoading }) }), jsx$1(Grid$1, { size: 12, children: jsxs(Grid$1, { container: true, direction: "row", spacing: 2, alignItems: "center", wrap: "nowrap", children: [jsx$1(LoadingControlButton, { startIcon: jsx$1(Stop, {}), onClick: onStopLoading, disabled: noNewRequests, ariaLabel: "Stop loading data and render at highest resolution", children: "Stop Loading" }), jsx$1(LoadingControlButton, { startIcon: jsx$1(Replay, {}), onClick: onRestartLoading, disabled: !noNewRequests && !isLoading, ariaLabel: "Restart data loading", children: "Restart Loading" })] }) }), jsx$1(Grid$1, { size: 12, visibility: isLoading ? "visible" : "hidden", mt: 1, mb: 0.5, children: jsx$1(LinearProgress, { variant: "determinate", value: percentage }) })] });
|
|
265307
265390
|
}
|
|
265308
|
-
const useStyles$
|
|
265391
|
+
const useStyles$9 = makeStyles()(() => ({
|
|
265309
265392
|
imageLayerButton: {
|
|
265310
265393
|
borderStyle: "dashed",
|
|
265311
265394
|
marginTop: "10px",
|
|
@@ -265448,7 +265531,7 @@ function ImageLayerController(props) {
|
|
|
265448
265531
|
}, [visible, setVisible]);
|
|
265449
265532
|
const handleOpacityChange = useCallback((e3, v) => setOpacity2(v), [setOpacity2]);
|
|
265450
265533
|
const handleOpenChange = useCallback(() => setOpen((prev2) => !prev2), []);
|
|
265451
|
-
const { classes: classes2 } = useStyles$
|
|
265534
|
+
const { classes: classes2 } = useStyles$9();
|
|
265452
265535
|
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
265453
265536
|
const { classes: controllerSectionClasses } = useControllerSectionStyles();
|
|
265454
265537
|
const isMultiChannel = photometricInterpretation !== "RGB";
|
|
@@ -265460,7 +265543,7 @@ function ImageLayerController(props) {
|
|
|
265460
265543
|
return jsx$1(ImageChannelController, { theme, coordinationScopesRaw, layerScope, channelScope: cScope, targetT, targetZ, targetC: channelIndex, setTargetC: setSpatialTargetC, visible: spatialChannelVisible, setVisible: setSpatialChannelVisible, opacity: spatialChannelOpacity, setOpacity: setSpatialChannelOpacity, color: spatialChannelColor, setColor: setSpatialChannelColor, window: spatialChannelWindow, setWindow: setSpatialChannelWindow, colormapOn: colormap !== null, featureIndex, image: image2, channelsSortOrder, spatialRenderingMode, numResolutions, spatialMaxResolution, setSpatialMaxResolution }, cScope);
|
|
265461
265544
|
}), jsx$1(Button, { disabled: channelScopes.length === MAX_CHANNELS$1 || channelScopes.length === imageNumChannels, onClick: handleChannelAdd, fullWidth: true, variant: "outlined", className: classes2.imageLayerButton, startIcon: jsx$1(AddIcon, {}), size: "small", "aria-label": "Add a channel to this layer", children: "Add Channel" })] }) : null, is3dMode && image2 ? jsxs(Grid$1, { container: true, direction: "column", justifyContent: "space-between", className: classes2.imageChannelControllerGrid, children: [jsx$1(Typography, { className: classes2.clippingPanesLabel, children: "Clipping planes:" }), jsx$1(Grid$1, { size: 12, className: classes2.clippingSliders, children: jsx$1(ClippingSliders, { image: image2, spatialSliceX, spatialSliceY, spatialSliceZ, setSpatialSliceX, setSpatialSliceY, setSpatialSliceZ }) }), jsx$1(LoadingStatusIndicator, { loadingProgress: volumeLoadingProgress, onStopLoading: onStopVolumeLoading, onRestartLoading: onRestartVolumeLoading, stillRef: volumeStillRef, spatialRenderingMode })] }) : null] }) });
|
|
265462
265545
|
}
|
|
265463
|
-
const useStyles$
|
|
265546
|
+
const useStyles$8 = makeStyles()((theme) => ({
|
|
265464
265547
|
dimensionsIcon: {
|
|
265465
265548
|
height: "40px",
|
|
265466
265549
|
width: "40px",
|
|
@@ -265484,7 +265567,7 @@ const useStyles$7 = makeStyles()((theme) => ({
|
|
|
265484
265567
|
function GlobalDimensionSlider(props) {
|
|
265485
265568
|
const { label: label2, targetValue, setTargetValue, min: min2 = 0, max: max2 = 0, spatialRenderingMode = null, setSpatialRenderingMode = null } = props;
|
|
265486
265569
|
const { classes: lcClasses } = useControllerSectionStyles();
|
|
265487
|
-
const { classes: classes2 } = useStyles$
|
|
265570
|
+
const { classes: classes2 } = useStyles$8();
|
|
265488
265571
|
const isForZ = spatialRenderingMode !== null;
|
|
265489
265572
|
const is3dMode = spatialRenderingMode === "3D";
|
|
265490
265573
|
function handleRenderingModeChange(event2) {
|
|
@@ -265495,17 +265578,112 @@ function GlobalDimensionSlider(props) {
|
|
|
265495
265578
|
}
|
|
265496
265579
|
return jsx$1(Grid$1, { className: lcClasses.layerControllerGrid, children: jsx$1(Paper, { elevation: 4, className: lcClasses.layerControllerRoot, children: jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsx$1(Grid$1, { size: 1, children: jsx$1(SvgDimensions, { className: classes2.dimensionsIcon }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(Typography, { className: classes2.dimensionLabel, children: label2 }) }), jsx$1(Grid$1, { size: 8, children: !is3dMode ? jsx$1(Slider, { value: targetValue, min: min2, max: max2, step: 1, onChange: (e3, v) => setTargetValue(v), className: classes2.dimensionSlider, valueLabelDisplay: "auto", orientation: "horizontal", disabled: spatialRenderingMode === "3D", "aria-label": `${label2}-slice slider` }) : null }), jsx$1(Grid$1, { size: 2, children: isForZ ? jsx$1(FormGroup, { row: true, className: classes2.switchFormGroup, children: jsx$1(FormControlLabel$1, { control: jsx$1(Switch, { color: "primary", checked: spatialRenderingMode === "3D", onChange: handleRenderingModeChange, name: "is3dMode" }), label: "3D" }) }) : null })] }) }) });
|
|
265497
265580
|
}
|
|
265581
|
+
const useStyles$7 = makeStyles()(() => ({
|
|
265582
|
+
layerTypeCentroidSegmentationIcon: {
|
|
265583
|
+
height: "100%",
|
|
265584
|
+
marginLeft: "1px",
|
|
265585
|
+
fill: "currentColor",
|
|
265586
|
+
fontSize: "24px",
|
|
265587
|
+
width: "50%",
|
|
265588
|
+
maxWidth: "24px"
|
|
265589
|
+
},
|
|
265590
|
+
divider: {
|
|
265591
|
+
width: "1px",
|
|
265592
|
+
height: "20px",
|
|
265593
|
+
background: "currentColor",
|
|
265594
|
+
flexShrink: 0,
|
|
265595
|
+
margin: "0 10px"
|
|
265596
|
+
},
|
|
265597
|
+
inlineLabel: {
|
|
265598
|
+
margin: "0px !important",
|
|
265599
|
+
lineHeight: 1,
|
|
265600
|
+
alignSelf: "center"
|
|
265601
|
+
},
|
|
265602
|
+
iconCell: {
|
|
265603
|
+
display: "flex",
|
|
265604
|
+
alignItems: "center",
|
|
265605
|
+
justifyContent: "center"
|
|
265606
|
+
}
|
|
265607
|
+
}));
|
|
265608
|
+
function CombinedEllipsisMenu(props) {
|
|
265609
|
+
const { obsType, featureType, featureValueType, filled, setFilled, strokeWidth, setStrokeWidth, obsColorEncoding, setObsColorEncoding, featureValueColormap, setFeatureValueColormap, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible, setPointObsColorEncoding, setPointFeatureValueColormap, setPointFeatureValueColormapRange, onColorEncodingChange } = props;
|
|
265610
|
+
const [open2, setOpen] = useState(false);
|
|
265611
|
+
const { classes: selectClasses2 } = useSelectStyles();
|
|
265612
|
+
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
265613
|
+
const filledId = $bdb11010cef70236$export$f680877a34711e37();
|
|
265614
|
+
const strokeWidthId = $bdb11010cef70236$export$f680877a34711e37();
|
|
265615
|
+
const colorEncodingId = $bdb11010cef70236$export$f680877a34711e37();
|
|
265616
|
+
const colormapId = $bdb11010cef70236$export$f680877a34711e37();
|
|
265617
|
+
const colormapRangeId = $bdb11010cef70236$export$f680877a34711e37();
|
|
265618
|
+
const tooltipsId = $bdb11010cef70236$export$f680877a34711e37();
|
|
265619
|
+
const crosshairsId = $bdb11010cef70236$export$f680877a34711e37();
|
|
265620
|
+
const legendId = $bdb11010cef70236$export$f680877a34711e37();
|
|
265621
|
+
return jsxs(PopperMenu, { open: open2, setOpen, buttonIcon: jsx$1(MoreVertIcon, {}), buttonClassName: menuClasses.imageLayerMenuButton, containerClassName: menuClasses.imageLayerPopperContainer, withPaper: true, getAriaLabel: () => "Open combined centroid and segmentation layer options menu", children: [jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: filledId, children: "Filled: " }), jsx$1(Checkbox$1, { color: "primary", className: menuClasses.menuItemCheckbox, checked: filled, onChange: (e3, v) => setFilled(v), slotProps: { input: { id: filledId } } })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: strokeWidthId, children: "Stroke width:" }), jsx$1(Slider, { disabled: filled, value: strokeWidth, min: 0.01, max: 5, step: 0.01, onChange: (e3, v) => setStrokeWidth(v), className: menuClasses.menuItemSlider, orientation: "horizontal", id: strokeWidthId, getAriaLabel: () => "Stroke width" })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: colorEncodingId, children: "Color encoding: " }), jsxs(NativeSelect, { onChange: onColorEncodingChange, value: obsColorEncoding, inputProps: { id: colorEncodingId }, classes: { root: selectClasses2.selectRoot }, children: [jsx$1("option", { value: "spatialChannelColor", children: "Static Color" }), jsx$1("option", { value: "geneSelection", children: "Feature Value" }), jsx$1("option", { value: "cellSetSelection", children: "Set Selection" })] })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: colormapId, children: "Colormap: " }), jsx$1(NativeSelect, { onChange: (e3) => {
|
|
265622
|
+
setFeatureValueColormap(e3.target.value);
|
|
265623
|
+
setPointFeatureValueColormap?.(e3.target.value);
|
|
265624
|
+
}, value: featureValueColormap, inputProps: { id: colormapId }, classes: { root: selectClasses2.selectRoot }, children: GLSL_COLORMAPS.map((cmap) => jsx$1("option", { value: cmap, children: cmap }, cmap)) })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: colormapRangeId, children: "Colormap range: " }), jsx$1(Slider, { disabled: obsColorEncoding !== "geneSelection", value: featureValueColormapRange, min: 0, max: 1, step: 0.01, onChange: (e3, v) => {
|
|
265625
|
+
setFeatureValueColormapRange(v);
|
|
265626
|
+
setPointFeatureValueColormapRange?.(v);
|
|
265627
|
+
}, className: menuClasses.menuItemSlider, orientation: "horizontal", id: colormapRangeId, getAriaLabel: (i2) => i2 === 0 ? "Low colormap range" : "High colormap range" })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: tooltipsId, children: "Tooltips visible: " }), jsx$1(Checkbox$1, { color: "primary", className: menuClasses.menuItemCheckbox, checked: tooltipsVisible, onChange: (e3, v) => setTooltipsVisible(v), slotProps: { input: { id: tooltipsId } } })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: crosshairsId, children: "Crosshairs visible: " }), jsx$1(Checkbox$1, { color: "primary", className: menuClasses.menuItemCheckbox, checked: tooltipCrosshairsVisible, onChange: (e3, v) => setTooltipCrosshairsVisible(v), slotProps: { input: { id: crosshairsId } } })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: legendId, children: "Legend visible: " }), jsx$1(Checkbox$1, { color: "primary", className: menuClasses.menuItemCheckbox, checked: legendVisible, onChange: (e3, v) => setLegendVisible(v), slotProps: { input: { id: legendId } } })] })] });
|
|
265628
|
+
}
|
|
265629
|
+
function SegmentationCentroidsController(props) {
|
|
265630
|
+
const { theme, segScope, segLayerCoordination, segChannelScopesByLayer, segChannelCoordination, pointScope, pointLayerCoordination } = props;
|
|
265631
|
+
const { classes: classes2 } = useStyles$7();
|
|
265632
|
+
const { classes: lcClasses } = useControllerSectionStyles();
|
|
265633
|
+
const { classes: menuClasses } = useEllipsisMenuStyles();
|
|
265634
|
+
const channelScopes = segChannelScopesByLayer?.[segScope] ?? [];
|
|
265635
|
+
const primaryChanScope = channelScopes[0];
|
|
265636
|
+
const chanValues = segChannelCoordination[0]?.[segScope]?.[primaryChanScope] ?? {};
|
|
265637
|
+
const chanSetters = segChannelCoordination[1]?.[segScope]?.[primaryChanScope] ?? {};
|
|
265638
|
+
const { obsType, featureType, featureValueType, spatialChannelVisible: segVisible, spatialChannelOpacity: segOpacity, spatialChannelColor: segColor, spatialSegmentationFilled: filled, spatialSegmentationStrokeWidth: strokeWidth, obsColorEncoding, featureSelection, featureValueColormap, featureValueColormapRange, tooltipsVisible, tooltipCrosshairsVisible, legendVisible } = chanValues;
|
|
265639
|
+
const { setSpatialChannelVisible: setSegVisible, setSpatialChannelOpacity: setSegOpacity, setSpatialChannelColor: setSegColor, setSpatialSegmentationFilled: setFilled, setSpatialSegmentationStrokeWidth: setStrokeWidth, setObsColorEncoding, setFeatureValueColormap, setFeatureValueColormapRange, setTooltipsVisible, setTooltipCrosshairsVisible, setLegendVisible } = chanSetters;
|
|
265640
|
+
const pointValues = pointLayerCoordination[0]?.[pointScope] ?? {};
|
|
265641
|
+
const pointSetters = pointLayerCoordination[1]?.[pointScope] ?? {};
|
|
265642
|
+
const { spatialLayerVisible: pointVisible, spatialLayerOpacity: pointOpacity, spatialLayerColor: pointColor, obsColorEncoding: pointObsColorEncoding, featureValueColormap: pointFeatureValueColormap } = pointValues;
|
|
265643
|
+
const { setSpatialLayerVisible: setPointVisible, setSpatialLayerOpacity: setPointOpacity, setSpatialLayerColor: setPointColor, setObsColorEncoding: setPointObsColorEncoding, setFeatureValueColormap: setPointFeatureValueColormap, setFeatureValueColormapRange: setPointFeatureValueColormapRange } = pointSetters;
|
|
265644
|
+
const sharedOpacity = segOpacity ?? 1;
|
|
265645
|
+
const handleOpacityChange = useCallback((e3, v) => {
|
|
265646
|
+
setSegOpacity?.(v);
|
|
265647
|
+
setPointOpacity?.(v);
|
|
265648
|
+
}, [setSegOpacity, setPointOpacity]);
|
|
265649
|
+
const handleSegVisibleChange = useCallback(() => {
|
|
265650
|
+
setSegVisible?.(typeof segVisible === "boolean" ? !segVisible : false);
|
|
265651
|
+
}, [segVisible, setSegVisible]);
|
|
265652
|
+
const handlePointVisibleChange = useCallback(() => {
|
|
265653
|
+
setPointVisible?.(typeof pointVisible === "boolean" ? !pointVisible : false);
|
|
265654
|
+
}, [pointVisible, setPointVisible]);
|
|
265655
|
+
const handleColorEncodingChange = useCallback((e3) => {
|
|
265656
|
+
const val = e3.target.value;
|
|
265657
|
+
setObsColorEncoding(val);
|
|
265658
|
+
if (val === "geneSelection") {
|
|
265659
|
+
setPointObsColorEncoding?.("geneSelection");
|
|
265660
|
+
} else if (val === "cellSetSelection") {
|
|
265661
|
+
setPointObsColorEncoding?.("cellSetSelection");
|
|
265662
|
+
} else {
|
|
265663
|
+
setPointObsColorEncoding?.("spatialChannelColor");
|
|
265664
|
+
}
|
|
265665
|
+
}, [setObsColorEncoding, setPointObsColorEncoding]);
|
|
265666
|
+
const segVisibleSetting = typeof segVisible === "boolean" ? segVisible : true;
|
|
265667
|
+
const pointVisibleSetting = typeof pointVisible === "boolean" ? pointVisible : true;
|
|
265668
|
+
const SegVisibility = segVisibleSetting ? VisibilityIcon : VisibilityOffIcon;
|
|
265669
|
+
const PointVisibility = pointVisibleSetting ? VisibilityIcon : VisibilityOffIcon;
|
|
265670
|
+
const isStaticColor = obsColorEncoding === "spatialChannelColor";
|
|
265671
|
+
const isColormap = obsColorEncoding === "geneSelection";
|
|
265672
|
+
const pointIsStaticColor = pointObsColorEncoding === "spatialChannelColor";
|
|
265673
|
+
const pointIsColormap = pointObsColorEncoding === "geneSelection";
|
|
265674
|
+
return jsx$1(Grid$1, { className: lcClasses.layerControllerGrid, children: jsx$1(Paper, { elevation: 4, className: lcClasses.layerControllerRoot, children: jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", alignItems: "center", children: [jsxs(Grid$1, { size: "grow", style: { display: "flex", alignItems: "center", minWidth: 0 }, children: [jsx$1(Button, { onClick: handleSegVisibleChange, className: menuClasses.imageLayerVisibleButton, getAriaLabel: () => "Toggle mesh visibility", children: jsx$1(SegVisibility, {}) }), jsx$1(ChannelColorPickerMenu, { theme, color: segColor, setColor: setSegColor, isStaticColor, isColormap, featureValueColormap, visible: segVisibleSetting }), jsx$1(Typography, { className: `${menuClasses.imageLayerName} ${classes2.inlineLabel}`, children: "Cell" }), jsx$1("div", { className: classes2.divider }), jsx$1(Button, { onClick: handlePointVisibleChange, className: menuClasses.imageLayerVisibleButton, getAriaLabel: () => "Toggle centroid visibility", children: jsx$1(PointVisibility, {}) }), jsx$1(ChannelColorPickerMenu, { theme, color: pointColor, setColor: setPointColor, isStaticColor: pointIsStaticColor, isColormap: pointIsColormap, featureValueColormap: pointFeatureValueColormap, visible: pointVisibleSetting }), jsx$1(Typography, { className: `${menuClasses.imageLayerName} ${classes2.inlineLabel}`, children: "Point" })] }), jsx$1(Grid$1, { size: 2, children: jsx$1(Slider, { value: sharedOpacity, min: 0, max: 1, step: 1e-3, onChange: handleOpacityChange, className: menuClasses.imageLayerOpacitySlider, orientation: "horizontal", getAriaLabel: () => "Adjust shared opacity" }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(CombinedEllipsisMenu, { obsType, featureType, featureValueType, filled, setFilled, strokeWidth, setStrokeWidth, obsColorEncoding, setObsColorEncoding, featureValueColormap, setFeatureValueColormap, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible, setPointObsColorEncoding, setPointFeatureValueColormap, setPointFeatureValueColormapRange, onColorEncodingChange: handleColorEncodingChange }) }), jsx$1(Grid$1, { size: 1, className: classes2.iconCell, children: jsx$1(SvgVector, { className: classes2.layerTypeCentroidSegmentationIcon }) })] }) }) });
|
|
265675
|
+
}
|
|
265498
265676
|
function LayerController(props) {
|
|
265499
|
-
const { theme, coordinationScopesRaw, segmentationLayerScopes, segmentationLayerCoordination, segmentationChannelScopesByLayer, segmentationChannelCoordination, images, imageLayerScopes, imageLayerCoordination, targetT, targetZ, setTargetT, setTargetZ, spatialRenderingMode, setSpatialRenderingMode, imageChannelScopesByLayer, imageChannelCoordination, spotLayerScopes, spotLayerCoordination, pointLayerScopes, pointLayerCoordination, pointMultiIndicesData, volumeLoadingStatus, tiledPointsLoadingProgress, layerPerFeatureForPoints } = props;
|
|
265677
|
+
const { theme, coordinationScopesRaw, segmentationLayerScopes, segmentationLayerCoordination, segmentationChannelScopesByLayer, segmentationChannelCoordination, images, imageLayerScopes, imageLayerCoordination, targetT, targetZ, setTargetT, setTargetZ, spatialRenderingMode, setSpatialRenderingMode, imageChannelScopesByLayer, imageChannelCoordination, spotLayerScopes, spotLayerCoordination, pointLayerScopes, pointLayerCoordination, pointMultiIndicesData, volumeLoadingStatus, tiledPointsLoadingProgress, layerPerFeatureForPoints, centroidSegmentationPairs = [], pairedSegScopes = /* @__PURE__ */ new Set(), pairedPointScopes = /* @__PURE__ */ new Set() } = props;
|
|
265500
265678
|
const anyLayerHasT = Object.values(images || {}).some((image2) => image2?.image?.instance.hasTStack());
|
|
265501
265679
|
const anyLayerHasZ = Object.values(images || {}).some((image2) => image2?.image?.instance.hasZStack());
|
|
265502
265680
|
const maxT = Object.values(images || {}).reduce((a2, h2) => Math.max(a2, h2?.image?.instance.getNumT()), 1) - 1;
|
|
265503
265681
|
const maxZ = Object.values(images || {}).reduce((a2, h2) => Math.max(a2, h2?.image?.instance.getNumZ()), 1) - 1;
|
|
265504
265682
|
const reversedImageLayerScopes = useMemo$1(() => [...imageLayerScopes || []].reverse(), [imageLayerScopes]);
|
|
265505
|
-
const reversedSegmentationLayerScopes = useMemo$1(() => [...segmentationLayerScopes || []].reverse(), [segmentationLayerScopes]);
|
|
265506
265683
|
const reversedSpotLayerScopes = useMemo$1(() => [...spotLayerScopes || []].reverse(), [spotLayerScopes]);
|
|
265507
|
-
const reversedPointLayerScopes = useMemo$1(() => [...pointLayerScopes || []].reverse(), [pointLayerScopes]);
|
|
265508
|
-
|
|
265684
|
+
const reversedPointLayerScopes = useMemo$1(() => [...pointLayerScopes || []].filter((scope) => !pairedPointScopes.has(scope)).reverse(), [pointLayerScopes, pairedPointScopes]);
|
|
265685
|
+
const reversedSegmentationLayerScopes = useMemo$1(() => [...segmentationLayerScopes || []].filter((scope) => !pairedSegScopes.has(scope)).reverse(), [segmentationLayerScopes, pairedSegScopes]);
|
|
265686
|
+
return jsxs("div", { children: [anyLayerHasZ ? jsx$1(GlobalDimensionSlider, { label: "Z", targetValue: targetZ, setTargetValue: setTargetZ, max: maxZ, spatialRenderingMode, setSpatialRenderingMode }) : null, anyLayerHasT ? jsx$1(GlobalDimensionSlider, { label: "T", targetValue: targetT, setTargetValue: setTargetT, max: maxT }) : null, centroidSegmentationPairs.map(({ pointScope, segScope }) => jsx$1(SegmentationCentroidsController, { theme, segScope, segLayerCoordination: segmentationLayerCoordination, segChannelScopesByLayer: segmentationChannelScopesByLayer, segChannelCoordination: segmentationChannelCoordination, pointScope, pointLayerCoordination }, `combined-${segScope}-${pointScope}`)), pointLayerScopes && reversedPointLayerScopes.map((layerScope) => jsx$1(PointLayerController, { theme, layerScope, layerCoordination: pointLayerCoordination[0][layerScope], setLayerCoordination: pointLayerCoordination[1][layerScope], pointMatrixIndicesData: pointMultiIndicesData?.[layerScope], tiledPointsLoadingProgress, layerPerFeatureForPoints }, layerScope)), spotLayerScopes && reversedSpotLayerScopes.map((layerScope) => jsx$1(SpotLayerController, { theme, layerScope, layerCoordination: spotLayerCoordination[0][layerScope], setLayerCoordination: spotLayerCoordination[1][layerScope] }, layerScope)), segmentationLayerScopes && reversedSegmentationLayerScopes.map((layerScope) => jsx$1(SegmentationLayerController, { theme, layerScope, layerCoordination: segmentationLayerCoordination[0][layerScope], setLayerCoordination: segmentationLayerCoordination[1][layerScope], channelScopes: segmentationChannelScopesByLayer[layerScope], channelCoordination: segmentationChannelCoordination[0][layerScope], setChannelCoordination: segmentationChannelCoordination[1][layerScope] }, layerScope)), imageLayerScopes && reversedImageLayerScopes.map((layerScope) => jsx$1(ImageLayerController, { theme, coordinationScopesRaw, layerScope, layerCoordination: imageLayerCoordination[0][layerScope], setLayerCoordination: imageLayerCoordination[1][layerScope], channelScopes: imageChannelScopesByLayer[layerScope], channelCoordination: imageChannelCoordination[0][layerScope], setChannelCoordination: imageChannelCoordination[1][layerScope], image: images[layerScope]?.image?.instance, featureIndex: images[layerScope]?.featureIndex, targetT, targetZ, spatialRenderingMode, volumeLoadingProgress: volumeLoadingStatus?.loadingProgress, onStopVolumeLoading: volumeLoadingStatus?.onStopLoading, onRestartVolumeLoading: volumeLoadingStatus?.onRestartLoading, volumeStillRef: volumeLoadingStatus?.stillRef }, layerScope))] });
|
|
265509
265687
|
}
|
|
265510
265688
|
function LayerControllerSubscriber(props) {
|
|
265511
265689
|
const { coordinationScopes: coordinationScopesRaw, coordinationScopesBy: coordinationScopesByRaw, closeButtonVisible, downloadButtonVisible, removeGridComponent, theme, title: title2 = "Spatial Layers", uuid: uuid2, layerPerFeatureForPoints = false, cameraPresets, helpText = ViewHelpMapping.LAYER_CONTROLLER_BETA } = props;
|
|
@@ -265638,6 +265816,40 @@ function LayerControllerSubscriber(props) {
|
|
|
265638
265816
|
CoordinationType$1.TOOLTIP_CROSSHAIRS_VISIBLE,
|
|
265639
265817
|
CoordinationType$1.LEGEND_VISIBLE
|
|
265640
265818
|
], coordinationScopes, coordinationScopesBy, CoordinationType$1.POINT_LAYER);
|
|
265819
|
+
const centroidSegmentationPairs = React__default.useMemo(() => {
|
|
265820
|
+
const pairs = [];
|
|
265821
|
+
const pairedSegScopes = /* @__PURE__ */ new Set();
|
|
265822
|
+
const pairedPointScopes = /* @__PURE__ */ new Set();
|
|
265823
|
+
pointLayerScopes.forEach((pointScope) => {
|
|
265824
|
+
const pointCoord = pointLayerCoordination[0][pointScope];
|
|
265825
|
+
if (!pointCoord)
|
|
265826
|
+
return;
|
|
265827
|
+
const pointObsType = pointCoord[CoordinationType$1.OBS_TYPE];
|
|
265828
|
+
if (!pointObsType)
|
|
265829
|
+
return;
|
|
265830
|
+
const matchingSegScope = segmentationLayerScopes.find((segScope) => {
|
|
265831
|
+
if (pairedSegScopes.has(segScope))
|
|
265832
|
+
return false;
|
|
265833
|
+
const channelScopes = segmentationChannelScopesByLayer[segScope] || [];
|
|
265834
|
+
return channelScopes.some((chanScope) => {
|
|
265835
|
+
const chanCoord = segmentationChannelCoordination[0]?.[segScope]?.[chanScope];
|
|
265836
|
+
return chanCoord?.[CoordinationType$1.OBS_TYPE] === pointObsType;
|
|
265837
|
+
});
|
|
265838
|
+
});
|
|
265839
|
+
if (matchingSegScope) {
|
|
265840
|
+
pairs.push({ pointScope, segScope: matchingSegScope });
|
|
265841
|
+
pairedSegScopes.add(matchingSegScope);
|
|
265842
|
+
pairedPointScopes.add(pointScope);
|
|
265843
|
+
}
|
|
265844
|
+
});
|
|
265845
|
+
return { pairs, pairedSegScopes, pairedPointScopes };
|
|
265846
|
+
}, [
|
|
265847
|
+
pointLayerScopes,
|
|
265848
|
+
pointLayerCoordination,
|
|
265849
|
+
segmentationLayerScopes,
|
|
265850
|
+
segmentationChannelScopesByLayer,
|
|
265851
|
+
segmentationChannelCoordination
|
|
265852
|
+
]);
|
|
265641
265853
|
const [{ volumeLoadingProgress: volumeLoadingStatus, tiledPointsLoadingProgress }] = useAuxiliaryCoordination([
|
|
265642
265854
|
"spatialAcceleratedVolumeLoadingProgress",
|
|
265643
265855
|
"spatialTiledPointsLoadingProgress"
|
|
@@ -265665,7 +265877,7 @@ function LayerControllerSubscriber(props) {
|
|
|
265665
265877
|
imageDataStatus,
|
|
265666
265878
|
pointMultiIndicesDataStatus
|
|
265667
265879
|
]);
|
|
265668
|
-
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 }) });
|
|
265880
|
+
return jsx$1(TitleInfo, { title: title2, isScroll: true, closeButtonVisible, downloadButtonVisible, removeGridComponent, theme, isReady, errors, helpText, children: jsx$1(LayerController, { theme, coordinationScopesRaw, segmentationLayerScopes, segmentationLayerCoordination, segmentationChannelScopesByLayer, segmentationChannelCoordination, images: imageData, imageLayerScopes, imageLayerCoordination, targetT, targetZ, setTargetT, setTargetZ, spatialRenderingMode, setSpatialRenderingMode, imageChannelScopesByLayer, imageChannelCoordination, spotLayerScopes, spotLayerCoordination, pointLayerScopes, pointLayerCoordination, pointMultiIndicesData, layerPerFeatureForPoints, volumeLoadingStatus, tiledPointsLoadingProgress, centroidSegmentationPairs: centroidSegmentationPairs.pairs, pairedSegScopes: centroidSegmentationPairs.pairedSegScopes, pairedPointScopes: centroidSegmentationPairs.pairedPointScopes }) });
|
|
265669
265881
|
}
|
|
265670
265882
|
const isIterable$2 = (obj) => Symbol.iterator in obj;
|
|
265671
265883
|
const hasIterableEntries = (value2) => (
|
|
@@ -267580,7 +267792,7 @@ function HiglassGlobalStyles(props) {
|
|
|
267580
267792
|
}
|
|
267581
267793
|
register({ dataFetcher: ZarrMultivecDataFetcher_default, config: ZarrMultivecDataFetcher_default.config }, { pluginType: "dataFetcher" });
|
|
267582
267794
|
const LazyHiGlassComponent = React__default.lazy(async () => {
|
|
267583
|
-
const { HiGlassComponent } = await import("./higlass-
|
|
267795
|
+
const { HiGlassComponent } = await import("./higlass-4OKx7mdy.js");
|
|
267584
267796
|
return { default: HiGlassComponent };
|
|
267585
267797
|
});
|
|
267586
267798
|
const HG_SIZE = 800;
|
|
@@ -267918,6 +268130,12 @@ const useStyles$4 = makeStyles()(() => ({
|
|
|
267918
268130
|
neuroglancerWrapper: {
|
|
267919
268131
|
position: "relative",
|
|
267920
268132
|
height: "100%"
|
|
268133
|
+
},
|
|
268134
|
+
meshLoadingIndicator: {
|
|
268135
|
+
position: "absolute",
|
|
268136
|
+
bottom: 8,
|
|
268137
|
+
left: 8,
|
|
268138
|
+
zIndex: 50
|
|
267921
268139
|
}
|
|
267922
268140
|
}));
|
|
267923
268141
|
const globalNeuroglancerCss = `
|
|
@@ -270531,7 +270749,7 @@ function NeuroglancerGlobalStyles(props) {
|
|
|
270531
270749
|
const { classes: classes2 } = props;
|
|
270532
270750
|
return jsxs(Fragment, { children: [jsx$1(GlobalStyles$3, { styles: globalNeuroglancerCss }), jsx$1(ScopedGlobalStyles, { styles: globalNeuroglancerStyles, parentClassName: classes2.neuroglancerWrapper })] });
|
|
270533
270751
|
}
|
|
270534
|
-
const LazyReactNeuroglancer = React__default.lazy(() => import("./ReactNeuroglancer-
|
|
270752
|
+
const LazyReactNeuroglancer = React__default.lazy(() => import("./ReactNeuroglancer-DSiLDSuM.js"));
|
|
270535
270753
|
function createWorker() {
|
|
270536
270754
|
const worker = new WorkerFactory$1();
|
|
270537
270755
|
worker.AsyncComputationWorker = WorkerFactory;
|
|
@@ -270576,12 +270794,31 @@ class NeuroglancerComp extends PureComponent {
|
|
|
270576
270794
|
}
|
|
270577
270795
|
};
|
|
270578
270796
|
remapWheelToZoom(viewer.inputEventBindings.perspectiveView);
|
|
270797
|
+
const { getMeshIdToCellId, onViewerReady, cellsUrl } = this.props;
|
|
270579
270798
|
this.prevHoverHandler = () => {
|
|
270580
|
-
|
|
270581
|
-
|
|
270582
|
-
|
|
270799
|
+
const ms = viewer.mouseState;
|
|
270800
|
+
if (ms.pickedAnnotationId != null) {
|
|
270801
|
+
const byIdKey = String(ms.pickedAnnotationId);
|
|
270802
|
+
fetch(`${cellsUrl}/by_id/${byIdKey}`).then((r3) => r3.arrayBuffer()).then((buf) => {
|
|
270803
|
+
const dv = new DataView(buf);
|
|
270804
|
+
const actualMeshId = String(dv.getInt32(12, true));
|
|
270805
|
+
const cellId = getMeshIdToCellId?.(actualMeshId) ?? actualMeshId;
|
|
270806
|
+
this.latestOnSelectHoveredCoords?.(cellId);
|
|
270807
|
+
});
|
|
270808
|
+
return;
|
|
270809
|
+
}
|
|
270810
|
+
if (ms.pickedValue !== void 0 && ms.pickedValue !== null) {
|
|
270811
|
+
const meshId = String(ms.pickedValue?.low);
|
|
270812
|
+
const cellId = getMeshIdToCellId?.(meshId) ?? meshId;
|
|
270813
|
+
this.latestOnSelectHoveredCoords?.(cellId);
|
|
270814
|
+
return;
|
|
270583
270815
|
}
|
|
270816
|
+
this.latestOnSelectHoveredCoords?.(null);
|
|
270584
270817
|
};
|
|
270818
|
+
onViewerReady?.(() => {
|
|
270819
|
+
const panel = [...viewer.display.panels][0];
|
|
270820
|
+
return panel?.projectionParameters?.value_?.viewProjectionMat;
|
|
270821
|
+
});
|
|
270585
270822
|
viewer.mouseState.changed.add(this.prevHoverHandler);
|
|
270586
270823
|
} else {
|
|
270587
270824
|
if (this.prevMouseStateChanged && this.prevHoverHandler) {
|
|
@@ -270602,8 +270839,8 @@ class NeuroglancerComp extends PureComponent {
|
|
|
270602
270839
|
}
|
|
270603
270840
|
}
|
|
270604
270841
|
render() {
|
|
270605
|
-
const { classes: classes2, viewerState, cellColorMapping, onLayerLoadingChange } = this.props;
|
|
270606
|
-
return jsxs(Fragment, { children: [jsx$1(NeuroglancerGlobalStyles, { classes: classes2 }), jsx$1("div", { className: classes2.neuroglancerWrapper, children: jsx$1(Suspense, { fallback: jsx$1("div", { children: "Loading..." }), children: jsx$1(LazyReactNeuroglancer, { brainMapsClientId: "NOT_A_VALID_ID", viewerState, onViewerStateChanged: this.onViewerStateChanged, onLayerLoadingChange, bundleRoot: this.bundleRoot, cellColorMapping, ref: this.onRef }) }) })] });
|
|
270842
|
+
const { classes: classes2, viewerState, cellColorMapping, onLayerLoadingChange, onAnnotationSourceReady, onViewerReady, meshOpacity } = this.props;
|
|
270843
|
+
return jsxs(Fragment, { children: [jsx$1(NeuroglancerGlobalStyles, { classes: classes2 }), jsx$1("div", { className: classes2.neuroglancerWrapper, children: jsx$1(Suspense, { fallback: jsx$1("div", { children: "Loading..." }), children: jsx$1(LazyReactNeuroglancer, { brainMapsClientId: "NOT_A_VALID_ID", viewerState, onViewerStateChanged: this.onViewerStateChanged, onLayerLoadingChange, bundleRoot: this.bundleRoot, cellColorMapping, ref: this.onRef, onAnnotationSourceReady, onViewerReady, meshOpacity }) }) })] });
|
|
270607
270844
|
}
|
|
270608
270845
|
}
|
|
270609
270846
|
function useMemoCustomComparison(factory2, dependencies2, customIsEqual) {
|
|
@@ -270618,17 +270855,22 @@ function useMemoCustomComparison(factory2, dependencies2, customIsEqual) {
|
|
|
270618
270855
|
}
|
|
270619
270856
|
const shallowDiff = (prevDeps, nextDeps, depName) => prevDeps[depName] !== nextDeps[depName];
|
|
270620
270857
|
const shallowDiffByLayer = (prevDeps, nextDeps, depName, scopeName) => prevDeps?.[depName]?.[scopeName] !== nextDeps?.[depName]?.[scopeName];
|
|
270858
|
+
const shallowDiffByChannel = (prevDeps, nextDeps, depName, firstName, secondName) => prevDeps?.[depName]?.[firstName]?.[secondName] !== nextDeps?.[depName]?.[firstName]?.[secondName];
|
|
270621
270859
|
const shallowDiffByChannelWithKeys = (prevDeps, nextDeps, depName, firstName, secondName, keys2) => keys2.some((k) => prevDeps?.[depName]?.[firstName]?.[secondName]?.[k] !== nextDeps?.[depName]?.[firstName]?.[secondName]?.[k]);
|
|
270622
270860
|
const shallowDiffByLayerCoordinationWithKeys = (prevDeps, nextDeps, depName, layerScope, keys2) => keys2.some((k) => prevDeps?.[depName]?.[0]?.[layerScope]?.[k] !== nextDeps?.[depName]?.[0]?.[layerScope]?.[k]);
|
|
270623
270861
|
const shallowDiffByChannelCoordinationWithKeys = (prevDeps, nextDeps, depName, layerScope, channelScope, keys2) => keys2.some((k) => prevDeps?.[depName]?.[0]?.[layerScope]?.[channelScope]?.[k] !== nextDeps?.[depName]?.[0]?.[layerScope]?.[channelScope]?.[k]);
|
|
270624
270862
|
function customIsEqualForCellColors(prevDeps, nextDeps) {
|
|
270625
270863
|
let forceUpdate = false;
|
|
270626
270864
|
const curriedShallowDiff = (depName) => shallowDiff(prevDeps, nextDeps, depName);
|
|
270865
|
+
const curriedShallowDiffByChannel = (depName, firstName, secondName) => shallowDiffByChannel(prevDeps, nextDeps, depName, firstName, secondName);
|
|
270627
270866
|
const curriedShallowDiffByChannelWithKeys = (depName, firstName, secondName, keys2) => shallowDiffByChannelWithKeys(prevDeps, nextDeps, depName, firstName, secondName, keys2);
|
|
270628
270867
|
const curriedShallowDiffByChannelCoordinationWithKeys = (depName, layerScope, channelScope, keys2) => shallowDiffByChannelCoordinationWithKeys(prevDeps, nextDeps, depName, layerScope, channelScope, keys2);
|
|
270629
270868
|
if (curriedShallowDiff("theme")) {
|
|
270630
270869
|
forceUpdate = true;
|
|
270631
270870
|
}
|
|
270871
|
+
if (curriedShallowDiff("csvLoaded")) {
|
|
270872
|
+
forceUpdate = true;
|
|
270873
|
+
}
|
|
270632
270874
|
if (["segmentationLayerScopes", "segmentationChannelScopesByLayer"].some(curriedShallowDiff)) {
|
|
270633
270875
|
forceUpdate = true;
|
|
270634
270876
|
} else {
|
|
@@ -270643,8 +270885,11 @@ function customIsEqualForCellColors(prevDeps, nextDeps) {
|
|
|
270643
270885
|
"obsSetSelection",
|
|
270644
270886
|
"additionalObsSets",
|
|
270645
270887
|
"spatialChannelColor",
|
|
270646
|
-
"spatialChannelOpacity"
|
|
270647
|
-
|
|
270888
|
+
"spatialChannelOpacity",
|
|
270889
|
+
"featureValueColormap",
|
|
270890
|
+
"featureValueColormapRange",
|
|
270891
|
+
"featureSelection"
|
|
270892
|
+
]) || curriedShallowDiffByChannel("segmentationMultiIndicesData", layerScope, channelScope) || curriedShallowDiffByChannel("segmentationMultiExpressionNormData", layerScope, channelScope)) {
|
|
270648
270893
|
forceUpdate = true;
|
|
270649
270894
|
}
|
|
270650
270895
|
});
|
|
@@ -270690,7 +270935,13 @@ function customIsEqualForInitialViewerState(prevDeps, nextDeps) {
|
|
|
270690
270935
|
"featureSelection",
|
|
270691
270936
|
"featureFilterMode",
|
|
270692
270937
|
"featureColor",
|
|
270693
|
-
"spatialPointStrokeWidth"
|
|
270938
|
+
"spatialPointStrokeWidth",
|
|
270939
|
+
"featureValueColormap",
|
|
270940
|
+
"featureValueColormapRange",
|
|
270941
|
+
"featureSelection",
|
|
270942
|
+
"obsSetColor",
|
|
270943
|
+
"obsSetSelection",
|
|
270944
|
+
"additionalObsSets"
|
|
270694
270945
|
]) || Math.abs(prevDeps?.pointLayerCoordination?.[0]?.[layerScope]?.spatialLayerOpacity - nextDeps?.pointLayerCoordination?.[0]?.[layerScope]?.spatialLayerOpacity) >= 0.05) {
|
|
270695
270946
|
forceUpdate = true;
|
|
270696
270947
|
}
|
|
@@ -270744,6 +270995,35 @@ function getSpatialLayerColorWithSelectionShader(staticColor, opacity2, featureI
|
|
|
270744
270995
|
}
|
|
270745
270996
|
`;
|
|
270746
270997
|
}
|
|
270998
|
+
function getObsSetSelectionFilteredShader(phenotypeColors, selectedIndices, opacity2, borderWidth = 0) {
|
|
270999
|
+
const numColors = phenotypeColors.length;
|
|
271000
|
+
const numSelected = selectedIndices.length;
|
|
271001
|
+
const normColors = phenotypeColors.map((c2) => normalizeColor(c2));
|
|
271002
|
+
const colorsDecl = `vec3 phenotypeColors[${numColors}] = vec3[${numColors}](${normColors.map((c2) => toVec3(c2)).join(", ")});`;
|
|
271003
|
+
const selectedDecl = `int selectedIndices[${numSelected}] = int[${numSelected}](${selectedIndices.join(", ")});`;
|
|
271004
|
+
return `
|
|
271005
|
+
void main() {
|
|
271006
|
+
int phenotype = prop_phenotype();
|
|
271007
|
+
${colorsDecl}
|
|
271008
|
+
${selectedDecl}
|
|
271009
|
+
bool isSelected = false;
|
|
271010
|
+
for (int i = 0; i < ${numSelected}; ++i) {
|
|
271011
|
+
if (phenotype == selectedIndices[i]) {
|
|
271012
|
+
isSelected = true;
|
|
271013
|
+
}
|
|
271014
|
+
}
|
|
271015
|
+
if (!isSelected) {
|
|
271016
|
+
discard;
|
|
271017
|
+
}
|
|
271018
|
+
vec3 color = vec3(0.5, 0.5, 0.5);
|
|
271019
|
+
if (phenotype >= 0 && phenotype < ${numColors}) {
|
|
271020
|
+
color = phenotypeColors[phenotype];
|
|
271021
|
+
}
|
|
271022
|
+
setColor(vec4(color, ${opacity2.toFixed(4)}));
|
|
271023
|
+
${borderWidthGlsl(borderWidth)}
|
|
271024
|
+
}
|
|
271025
|
+
`;
|
|
271026
|
+
}
|
|
270747
271027
|
function getSpatialLayerColorFilteredShader(staticColor, opacity2, featureIndices, featureIndexProp, borderWidth = 0) {
|
|
270748
271028
|
const normStatic = normalizeColor(staticColor);
|
|
270749
271029
|
const numFeatures = featureIndices.length;
|
|
@@ -270925,6 +271205,23 @@ function getRandomPerPointShader(opacity2, featureIndexProp, pointIndexProp, bor
|
|
|
270925
271205
|
}
|
|
270926
271206
|
`;
|
|
270927
271207
|
}
|
|
271208
|
+
function getQuantitativeColormapShader(quantitativeColorProp, opacity2, colormap = GLSL_COLORMAP_DEFAULT, colormapRange = [0, 1], borderWidth = 0, quantitativeColorMax = 1) {
|
|
271209
|
+
const [low, high] = colormapRange;
|
|
271210
|
+
const resolvedColormap = GLSL_COLORMAPS.includes(colormap) ? colormap : GLSL_COLORMAP_DEFAULT;
|
|
271211
|
+
return `
|
|
271212
|
+
#define COLORMAP_FUNC ${resolvedColormap}
|
|
271213
|
+
${colormaps$1}
|
|
271214
|
+
void main() {
|
|
271215
|
+
float rawVal = float(prop_${quantitativeColorProp}());
|
|
271216
|
+
float normalizedVal = rawVal / ${quantitativeColorMax.toFixed(4)};
|
|
271217
|
+
float t = (normalizedVal - ${low.toFixed(4)}) / max(${(high - low).toFixed(4)}, 0.0001);
|
|
271218
|
+
t = clamp(t, 0.0, 1.0);
|
|
271219
|
+
vec4 col = COLORMAP_FUNC(t);
|
|
271220
|
+
setColor(vec4(col.rgb, ${opacity2.toFixed(4)}));
|
|
271221
|
+
${borderWidthGlsl(borderWidth)}
|
|
271222
|
+
}
|
|
271223
|
+
`;
|
|
271224
|
+
}
|
|
270928
271225
|
function getRandomPerPointWithSelectionShader(featureIndices, defaultColor, opacity2, featureIndexProp, pointIndexProp, borderWidth = 0) {
|
|
270929
271226
|
const normDefault = normalizeColor(defaultColor);
|
|
270930
271227
|
const numFeatures = featureIndices.length;
|
|
@@ -270980,8 +271277,25 @@ function getRandomPerPointFilteredShader(featureIndices, opacity2, featureIndexP
|
|
|
270980
271277
|
}
|
|
270981
271278
|
`;
|
|
270982
271279
|
}
|
|
271280
|
+
function getObsSetSelectionShader(phenotypeColors, opacity2, borderWidth = 0) {
|
|
271281
|
+
const numColors = phenotypeColors.length;
|
|
271282
|
+
const normColors = phenotypeColors.map((c2) => normalizeColor(c2));
|
|
271283
|
+
const colorsDecl = `vec3 phenotypeColors[${numColors}] = vec3[${numColors}](${normColors.map((c2) => toVec3(c2)).join(", ")});`;
|
|
271284
|
+
return `
|
|
271285
|
+
void main() {
|
|
271286
|
+
int phenotype = prop_phenotype();
|
|
271287
|
+
${colorsDecl}
|
|
271288
|
+
vec3 color = ${toVec3(normalizeColor([128, 128, 128]))};
|
|
271289
|
+
if (phenotype >= 0 && phenotype < ${numColors}) {
|
|
271290
|
+
color = phenotypeColors[phenotype];
|
|
271291
|
+
}
|
|
271292
|
+
setColor(vec4(color, ${opacity2.toFixed(4)}));
|
|
271293
|
+
${borderWidthGlsl(borderWidth)}
|
|
271294
|
+
}
|
|
271295
|
+
`;
|
|
271296
|
+
}
|
|
270983
271297
|
function getPointsShader(layerCoordination) {
|
|
270984
|
-
const { theme, featureIndex, spatialLayerOpacity, obsColorEncoding, spatialLayerColor, featureSelection, featureFilterMode, featureColor, pointMarkerBorderWidth = 0, featureIndexProp, pointIndexProp } = layerCoordination;
|
|
271298
|
+
const { theme, featureIndex, spatialLayerOpacity, obsColorEncoding, spatialLayerColor, featureSelection, featureFilterMode, featureColor, pointMarkerBorderWidth = 0, featureIndexProp, pointIndexProp, quantitativeColorProp, featureValueColormap, featureValueColormapRange, obsSetColor, obsSetSelection, quantitativeColorMax, pointsAreSegmentationCentroids } = layerCoordination;
|
|
270985
271299
|
const defaultColor = getDefaultColor(theme);
|
|
270986
271300
|
const opacity2 = spatialLayerOpacity ?? 1;
|
|
270987
271301
|
const staticColor = Array.isArray(spatialLayerColor) && spatialLayerColor.length === 3 ? spatialLayerColor : defaultColor;
|
|
@@ -271005,7 +271319,7 @@ function getPointsShader(layerCoordination) {
|
|
|
271005
271319
|
}
|
|
271006
271320
|
return getSpatialLayerColorWithSelectionShader(staticColor, opacity2, featureIndices, defaultColor, featureIndexProp, pointMarkerBorderWidth);
|
|
271007
271321
|
}
|
|
271008
|
-
if (obsColorEncoding === "geneSelection") {
|
|
271322
|
+
if (obsColorEncoding === "geneSelection" && !pointsAreSegmentationCentroids) {
|
|
271009
271323
|
if (!featureIndexProp) {
|
|
271010
271324
|
throw new Error("In order to use gene-based color encoding for Neuroglancer Points, options.featureIndexProp must be specified for the obsPoints.ng-annotations fileType in the Vitessce configuration.");
|
|
271011
271325
|
}
|
|
@@ -271041,19 +271355,49 @@ function getPointsShader(layerCoordination) {
|
|
|
271041
271355
|
}
|
|
271042
271356
|
return getRandomPerPointWithSelectionShader(featureIndices, defaultColor, opacity2, featureIndexProp, pointIndexProp, pointMarkerBorderWidth);
|
|
271043
271357
|
}
|
|
271358
|
+
if (obsColorEncoding === "geneSelection" && pointsAreSegmentationCentroids) {
|
|
271359
|
+
if (!quantitativeColorProp) {
|
|
271360
|
+
console.warn("In order to use quantitative colormap encoding for Neuroglancer Points, options.quantitativeColorProp must be specified for the obsPoints.ng-annotations fileType in the Vitessce configuration. Falling back to static color.");
|
|
271361
|
+
return getSpatialLayerColorShader(staticColor, opacity2, pointMarkerBorderWidth);
|
|
271362
|
+
}
|
|
271363
|
+
return getQuantitativeColormapShader(quantitativeColorProp, opacity2, featureValueColormap, featureValueColormapRange, pointMarkerBorderWidth, quantitativeColorMax);
|
|
271364
|
+
}
|
|
271365
|
+
if (obsColorEncoding === "cellSetSelection") {
|
|
271366
|
+
if (!obsSetColor || !obsSetSelection) {
|
|
271367
|
+
return getSpatialLayerColorShader(staticColor, opacity2, pointMarkerBorderWidth);
|
|
271368
|
+
}
|
|
271369
|
+
const colorByName = {};
|
|
271370
|
+
obsSetColor?.forEach(({ path: path2, color: color2 }) => {
|
|
271371
|
+
if (path2?.length > 1) {
|
|
271372
|
+
colorByName[path2[path2.length - 1]] = color2;
|
|
271373
|
+
}
|
|
271374
|
+
});
|
|
271375
|
+
const uniqueNames = Object.keys(colorByName).sort();
|
|
271376
|
+
const phenotypeColors = uniqueNames.map((name2) => colorByName[name2] ?? defaultColor);
|
|
271377
|
+
if (isFiltered) {
|
|
271378
|
+
const selectedNames = new Set(obsSetSelection?.map((path2) => path2[path2.length - 1]) ?? []);
|
|
271379
|
+
const selectedIndices = uniqueNames.map((name2, idx) => selectedNames.has(name2) ? idx : -1).filter((idx) => idx >= 0);
|
|
271380
|
+
if (selectedIndices.length === 0) {
|
|
271381
|
+
return "void main() { discard; }";
|
|
271382
|
+
}
|
|
271383
|
+
return getObsSetSelectionFilteredShader(phenotypeColors, selectedIndices, opacity2, pointMarkerBorderWidth);
|
|
271384
|
+
}
|
|
271385
|
+
return getObsSetSelectionShader(phenotypeColors, opacity2, pointMarkerBorderWidth);
|
|
271386
|
+
}
|
|
271044
271387
|
return getSpatialLayerColorShader(staticColor, opacity2, pointMarkerBorderWidth);
|
|
271045
271388
|
}
|
|
271389
|
+
const DEFAULT_NG_DIMENSIONS = {
|
|
271390
|
+
x: [1, "nm"],
|
|
271391
|
+
y: [1, "nm"],
|
|
271392
|
+
z: [1, "nm"]
|
|
271393
|
+
};
|
|
271046
271394
|
const DEFAULT_NG_PROPS = {
|
|
271047
271395
|
layout: "3d",
|
|
271048
271396
|
position: [0, 0, 0],
|
|
271049
271397
|
projectionOrientation: [0, 0, 0, 1],
|
|
271050
271398
|
projectionScale: 1024,
|
|
271051
271399
|
crossSectionScale: 1,
|
|
271052
|
-
dimensions:
|
|
271053
|
-
x: [1, "nm"],
|
|
271054
|
-
y: [1, "nm"],
|
|
271055
|
-
z: [1, "nm"]
|
|
271056
|
-
},
|
|
271400
|
+
dimensions: DEFAULT_NG_DIMENSIONS,
|
|
271057
271401
|
layers: []
|
|
271058
271402
|
};
|
|
271059
271403
|
function toPrecomputedSource(url) {
|
|
@@ -271071,6 +271415,15 @@ function toNgLayerName(dataType, layerScope, channelScope = null) {
|
|
|
271071
271415
|
}
|
|
271072
271416
|
throw new Error(`Unsupported data type: ${dataType}`);
|
|
271073
271417
|
}
|
|
271418
|
+
function pointsHaveMatchingSegmentation({ pointObsType, segmentationLayerScopes, segmentationChannelScopesByLayer, segmentationChannelCoordination }) {
|
|
271419
|
+
return segmentationLayerScopes.some((segmentationLayerScope) => {
|
|
271420
|
+
const segmentationChannelScopes = segmentationChannelScopesByLayer?.[segmentationLayerScope] || [];
|
|
271421
|
+
return segmentationChannelScopes.some((segmentationChannelScope) => {
|
|
271422
|
+
const segmentationObsType = segmentationChannelCoordination?.[0]?.[segmentationLayerScope]?.[segmentationChannelScope]?.obsType;
|
|
271423
|
+
return segmentationObsType && pointObsType && segmentationObsType === pointObsType;
|
|
271424
|
+
});
|
|
271425
|
+
});
|
|
271426
|
+
}
|
|
271074
271427
|
function useNeuroglancerViewerState(theme, showAxisLines, segmentationLayerScopes, segmentationChannelScopesByLayer, segmentationLayerCoordination, segmentationChannelCoordination, obsSegmentationsUrls, obsSegmentationsData, pointLayerScopes, pointLayerCoordination, obsPointsUrls, obsPointsData, pointMultiIndicesData) {
|
|
271075
271428
|
const viewerState = useMemoCustomComparison(() => {
|
|
271076
271429
|
let result = cloneDeep$1(DEFAULT_NG_PROPS);
|
|
@@ -271093,6 +271446,9 @@ function useNeuroglancerViewerState(theme, showAxisLines, segmentationLayerScope
|
|
|
271093
271446
|
} : toPrecomputedSource(layerUrl);
|
|
271094
271447
|
result = {
|
|
271095
271448
|
...result,
|
|
271449
|
+
showAxisLines,
|
|
271450
|
+
showDefaultAnnotations: false,
|
|
271451
|
+
// this removes the yellow box around pointsLayer
|
|
271096
271452
|
layers: [
|
|
271097
271453
|
...result.layers,
|
|
271098
271454
|
{
|
|
@@ -271116,9 +271472,27 @@ function useNeuroglancerViewerState(theme, showAxisLines, segmentationLayerScope
|
|
|
271116
271472
|
const layerCoordination = pointLayerCoordination[0][layerScope];
|
|
271117
271473
|
const layerData = obsPointsData[layerScope];
|
|
271118
271474
|
const layerUrl = obsPointsUrls[layerScope]?.[0]?.url;
|
|
271475
|
+
const ngOptions = layerData?.neuroglancerOptions;
|
|
271476
|
+
if (ngOptions?.transform?.matrix && ngOptions?.transform?.outputDimensions) {
|
|
271477
|
+
result = {
|
|
271478
|
+
...result,
|
|
271479
|
+
dimensions: ngOptions.transform.outputDimensions ?? DEFAULT_NG_DIMENSIONS
|
|
271480
|
+
};
|
|
271481
|
+
}
|
|
271482
|
+
const pointsAreSegmentationCentroids = pointsHaveMatchingSegmentation({
|
|
271483
|
+
pointObsType: layerCoordination?.obsType,
|
|
271484
|
+
segmentationLayerScopes,
|
|
271485
|
+
segmentationChannelScopesByLayer,
|
|
271486
|
+
segmentationChannelCoordination
|
|
271487
|
+
});
|
|
271119
271488
|
const featureIndex = pointMultiIndicesData[layerScope]?.featureIndex;
|
|
271120
271489
|
if (layerUrl && layerData) {
|
|
271121
|
-
const { spatialLayerVisible, spatialLayerOpacity, obsColorEncoding, spatialLayerColor, featureSelection, featureFilterMode, featureColor, spatialPointStrokeWidth } = layerCoordination || {};
|
|
271490
|
+
const { spatialLayerVisible, spatialLayerOpacity, obsColorEncoding, spatialLayerColor, featureSelection, featureFilterMode, featureColor, spatialPointStrokeWidth, featureValueColormap, featureValueColormapRange } = layerCoordination || {};
|
|
271491
|
+
const quantitativeColorMax = layerData.neuroglancerOptions?.quantitativeColorMax;
|
|
271492
|
+
if (!quantitativeColorMax && obsColorEncoding === "geneSelection") {
|
|
271493
|
+
console.warn("quantitativeColorMax not specified in options — defaulting to 1.0 (no normalization)");
|
|
271494
|
+
}
|
|
271495
|
+
const quantitativeColorMaxSelected = quantitativeColorMax ?? 1;
|
|
271122
271496
|
const shader = getPointsShader({
|
|
271123
271497
|
theme,
|
|
271124
271498
|
featureIndex,
|
|
@@ -271128,9 +271502,18 @@ function useNeuroglancerViewerState(theme, showAxisLines, segmentationLayerScope
|
|
|
271128
271502
|
featureSelection,
|
|
271129
271503
|
featureFilterMode,
|
|
271130
271504
|
featureColor,
|
|
271505
|
+
featureValueColormap,
|
|
271506
|
+
featureValueColormapRange,
|
|
271131
271507
|
featureIndexProp: layerData.neuroglancerOptions?.featureIndexProp,
|
|
271132
271508
|
pointIndexProp: layerData.neuroglancerOptions?.pointIndexProp,
|
|
271133
|
-
|
|
271509
|
+
quantitativeColorProp: layerData.neuroglancerOptions?.quantitativeColorProp,
|
|
271510
|
+
pointMarkerBorderWidth: spatialPointStrokeWidth ?? 0,
|
|
271511
|
+
obsSets: layerCoordination.obsSets,
|
|
271512
|
+
obsSetColor: layerCoordination.obsSetColor,
|
|
271513
|
+
obsSetSelection: layerCoordination.obsSetSelection,
|
|
271514
|
+
additionalObsSets: layerCoordination.additionalObsSets,
|
|
271515
|
+
quantitativeColorMax: quantitativeColorMaxSelected,
|
|
271516
|
+
pointsAreSegmentationCentroids
|
|
271134
271517
|
});
|
|
271135
271518
|
result = {
|
|
271136
271519
|
...result,
|
|
@@ -271143,7 +271526,13 @@ function useNeuroglancerViewerState(theme, showAxisLines, segmentationLayerScope
|
|
|
271143
271526
|
subsources: {
|
|
271144
271527
|
default: true
|
|
271145
271528
|
},
|
|
271146
|
-
enableDefaultSubsources: false
|
|
271529
|
+
enableDefaultSubsources: false,
|
|
271530
|
+
...ngOptions?.transform?.matrix ? {
|
|
271531
|
+
transform: {
|
|
271532
|
+
matrix: ngOptions.transform.matrix,
|
|
271533
|
+
outputDimensions: ngOptions.transform?.outputDimensions ?? result.dimensions
|
|
271534
|
+
}
|
|
271535
|
+
} : {}
|
|
271147
271536
|
},
|
|
271148
271537
|
tab: "annotations",
|
|
271149
271538
|
shader,
|
|
@@ -271151,7 +271540,7 @@ function useNeuroglancerViewerState(theme, showAxisLines, segmentationLayerScope
|
|
|
271151
271540
|
visible: spatialLayerVisible,
|
|
271152
271541
|
// Options from layerData.neuroglancerOptions
|
|
271153
271542
|
// like projectionAnnotationSpacing:
|
|
271154
|
-
projectionAnnotationSpacing:
|
|
271543
|
+
projectionAnnotationSpacing: ngOptions?.projectionAnnotationSpacing ?? 1
|
|
271155
271544
|
}
|
|
271156
271545
|
],
|
|
271157
271546
|
// TODO: is this needed?
|
|
@@ -271182,6 +271571,8 @@ function useNeuroglancerViewerState(theme, showAxisLines, segmentationLayerScope
|
|
|
271182
271571
|
}, customIsEqualForInitialViewerState);
|
|
271183
271572
|
return viewerState;
|
|
271184
271573
|
}
|
|
271574
|
+
const ANNOTATION_HEADER_OFFSET = 8;
|
|
271575
|
+
const GREY_HEX = "#323232";
|
|
271185
271576
|
const EPSILON_KEYS_MAPPING_NG = {
|
|
271186
271577
|
projectionScale: 100,
|
|
271187
271578
|
projectionOrientation: 0.02,
|
|
@@ -271202,6 +271593,17 @@ const multiplyQuat = (a2, b2) => {
|
|
|
271202
271593
|
const conjQuat = (q) => [-q[0], -q[1], -q[2], q[3]];
|
|
271203
271594
|
const rad2deg = (r3) => r3 * 180 / Math.PI;
|
|
271204
271595
|
const deg2rad = (d) => d * Math.PI / 180;
|
|
271596
|
+
function applyColormap(colormap, t4) {
|
|
271597
|
+
const tClamped = Math.max(0, Math.min(1, t4));
|
|
271598
|
+
const interpolators = {
|
|
271599
|
+
plasma: interpolatePlasma,
|
|
271600
|
+
viridis: interpolateViridis,
|
|
271601
|
+
jet: interpolateJet,
|
|
271602
|
+
greys: interpolateGreys
|
|
271603
|
+
};
|
|
271604
|
+
const fn2 = interpolators[colormap] ?? interpolateViridis;
|
|
271605
|
+
return fn2(tClamped);
|
|
271606
|
+
}
|
|
271205
271607
|
function valueGreaterThanEpsilon(a2, b2, epsilon3) {
|
|
271206
271608
|
if (Array.isArray(a2) && Array.isArray(b2) && a2.length === b2.length) {
|
|
271207
271609
|
return a2.some((val, i2) => Math.abs(val - b2[i2]) > epsilon3);
|
|
@@ -271268,13 +271670,57 @@ function makeVitNgZoomCalibrator(initialNgProjectionScale, initialDeckZoom = 0)
|
|
|
271268
271670
|
}
|
|
271269
271671
|
};
|
|
271270
271672
|
}
|
|
271673
|
+
function parseAnnotationChunkSegmentsWithPositions(buffer2, serializer2) {
|
|
271674
|
+
const dv = new DataView(buffer2);
|
|
271675
|
+
if (buffer2.byteLength <= 8)
|
|
271676
|
+
return [];
|
|
271677
|
+
const count2 = dv.getUint32(0, true);
|
|
271678
|
+
if (count2 === 0)
|
|
271679
|
+
return [];
|
|
271680
|
+
const numBytes = serializer2.serializedBytes;
|
|
271681
|
+
const properties2 = [null, null, null, null, null];
|
|
271682
|
+
const results = [];
|
|
271683
|
+
for (let i2 = 0; i2 < count2; i2++) {
|
|
271684
|
+
serializer2.deserialize(dv, ANNOTATION_HEADER_OFFSET, i2, count2, true, properties2);
|
|
271685
|
+
const phenotype = properties2[0];
|
|
271686
|
+
const segId = properties2[1];
|
|
271687
|
+
if (segId > 0) {
|
|
271688
|
+
const propBase = ANNOTATION_HEADER_OFFSET + i2 * numBytes;
|
|
271689
|
+
const x2 = dv.getFloat32(propBase + 0, true);
|
|
271690
|
+
const y2 = dv.getFloat32(propBase + 4, true);
|
|
271691
|
+
const z2 = dv.getFloat32(propBase + 8, true);
|
|
271692
|
+
if (x2 !== 0 || y2 !== 0 || z2 !== 0) {
|
|
271693
|
+
results.push({
|
|
271694
|
+
id: String(segId),
|
|
271695
|
+
// mesh segment ID - use for segments array
|
|
271696
|
+
phenotype: Number(phenotype),
|
|
271697
|
+
x: x2,
|
|
271698
|
+
y: y2,
|
|
271699
|
+
z: z2
|
|
271700
|
+
});
|
|
271701
|
+
}
|
|
271702
|
+
}
|
|
271703
|
+
}
|
|
271704
|
+
return results;
|
|
271705
|
+
}
|
|
271706
|
+
const remapCellColors = (ngCellColors, cellIdToMeshIdRef) => {
|
|
271707
|
+
const remapped = {};
|
|
271708
|
+
Object.entries(ngCellColors).forEach(([cellId, color2]) => {
|
|
271709
|
+
const meshId = cellIdToMeshIdRef.current[cellId] ?? cellId;
|
|
271710
|
+
remapped[meshId] = color2;
|
|
271711
|
+
});
|
|
271712
|
+
return remapped;
|
|
271713
|
+
};
|
|
271271
271714
|
const VITESSCE_INTERACTION_DELAY = 50;
|
|
271272
271715
|
const INIT_VIT_ZOOM = -3.6;
|
|
271273
271716
|
const ZOOM_EPS = 0.01;
|
|
271274
271717
|
const ROTATION_EPS = 1e-3;
|
|
271275
271718
|
const TARGET_EPS = 0.5;
|
|
271276
271719
|
const NG_ROT_COOLDOWN_MS = 120;
|
|
271720
|
+
const MESH_LOAD_THRESHOLD = 100;
|
|
271721
|
+
const MESH_LOADING_OVERLAY_TIMEOUT = 1500;
|
|
271277
271722
|
const GUIDE_URL = "https://vitessce.io/docs/ng-guide/";
|
|
271723
|
+
const MESH_OPACITY = 0.6;
|
|
271278
271724
|
const LAST_INTERACTION_SOURCE = {
|
|
271279
271725
|
vitessce: "vitessce",
|
|
271280
271726
|
neuroglancer: "neuroglancer"
|
|
@@ -271291,10 +271737,11 @@ function NeuroglancerSubscriber(props) {
|
|
|
271291
271737
|
downloadButtonVisible,
|
|
271292
271738
|
removeGridComponent,
|
|
271293
271739
|
theme,
|
|
271294
|
-
showAxisLines =
|
|
271740
|
+
showAxisLines = true,
|
|
271295
271741
|
title: title2 = "Spatial",
|
|
271296
271742
|
subtitle = "Powered by Neuroglancer",
|
|
271297
271743
|
helpText = ViewHelpMapping.NEUROGLANCER,
|
|
271744
|
+
meshLoadProjectionScaleThreshold,
|
|
271298
271745
|
// Note: this is a temporary mechanism
|
|
271299
271746
|
// to pass an initial NG camera state.
|
|
271300
271747
|
// Ideally, all camera state should be passed via
|
|
@@ -271305,6 +271752,32 @@ function NeuroglancerSubscriber(props) {
|
|
|
271305
271752
|
} = props;
|
|
271306
271753
|
const loaders = useLoaders();
|
|
271307
271754
|
const mergeCoordination = useMergeCoordination();
|
|
271755
|
+
const { classes: classes2 } = useStyles$4();
|
|
271756
|
+
const initialRotationPushedRef = useRef(false);
|
|
271757
|
+
const getViewProjectionMatRef = useRef(null);
|
|
271758
|
+
const obsIdToMeshIdRef = useRef({});
|
|
271759
|
+
const meshIdToCellIdRef = useRef({});
|
|
271760
|
+
const cellIdToMeshIdRef = useRef({});
|
|
271761
|
+
const ngRotPushAtRef = useRef(0);
|
|
271762
|
+
const lastInteractionSource = useRef(null);
|
|
271763
|
+
const applyNgUpdateTimeoutRef = useRef(null);
|
|
271764
|
+
const lastNgPushOrientationRef = useRef(null);
|
|
271765
|
+
const initialRenderCalibratorRef = useRef(null);
|
|
271766
|
+
const translationOffsetRef = useRef([0, 0, 0]);
|
|
271767
|
+
const zoomRafRef = useRef(null);
|
|
271768
|
+
const lastNgQuatRef = useRef([0, 0, 0, 1]);
|
|
271769
|
+
const lastNgScaleRef = useRef(null);
|
|
271770
|
+
const annotationInfoRef = useRef(null);
|
|
271771
|
+
const annotationTransformRef = useRef(null);
|
|
271772
|
+
const visibleSegmentIdsRef = useRef(null);
|
|
271773
|
+
const chunkCacheRef = useRef(/* @__PURE__ */ new Map());
|
|
271774
|
+
const resizeObserverRef = useRef(null);
|
|
271775
|
+
const [isLayersLoaded, setIsLayersLoaded] = useState(false);
|
|
271776
|
+
const [isMeshLoading, setIsMeshLoading] = useState(false);
|
|
271777
|
+
const [annotationReady, setAnnotationReady] = useState(false);
|
|
271778
|
+
const [csvLoaded, setCsvLoaded] = useState(false);
|
|
271779
|
+
const updateVisibleSegmentsThrottledRef = useRef(null);
|
|
271780
|
+
const viewportSizeRef = useRef({ width: 0, height: 0 });
|
|
271308
271781
|
const coordinationScopes = useCoordinationScopes(coordinationScopesRaw);
|
|
271309
271782
|
const coordinationScopesBy = useCoordinationScopesBy(coordinationScopes, coordinationScopesByRaw);
|
|
271310
271783
|
const [{
|
|
@@ -271336,6 +271809,19 @@ function NeuroglancerSubscriber(props) {
|
|
|
271336
271809
|
setSpatialRotationOrbit: setRotationOrbit,
|
|
271337
271810
|
setSpatialZoom: setZoom
|
|
271338
271811
|
}] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType$1.NEUROGLANCER], coordinationScopes);
|
|
271812
|
+
const csvUrlRef = useRef(null);
|
|
271813
|
+
const csvUrl = useMemo$1(() => {
|
|
271814
|
+
if (csvUrlRef.current)
|
|
271815
|
+
return csvUrlRef.current;
|
|
271816
|
+
const obsSetsMap = loaders?.[dataset]?.loaders?.obsSets;
|
|
271817
|
+
if (!obsSetsMap)
|
|
271818
|
+
return null;
|
|
271819
|
+
const firstLoader = obsSetsMap.values().next().value;
|
|
271820
|
+
const url = firstLoader?.url ?? null;
|
|
271821
|
+
if (url)
|
|
271822
|
+
csvUrlRef.current = url;
|
|
271823
|
+
return url;
|
|
271824
|
+
}, [loaders, dataset]);
|
|
271339
271825
|
const [ngWidth, ngHeight, containerRef] = useGridItemSize();
|
|
271340
271826
|
const [segmentationLayerScopes, segmentationChannelScopesByLayer] = useMultiCoordinationScopesSecondaryNonNull(CoordinationType$1.SEGMENTATION_CHANNEL, CoordinationType$1.SEGMENTATION_LAYER, coordinationScopes, coordinationScopesBy);
|
|
271341
271827
|
const pointLayerScopes = useMultiCoordinationScopesNonNull(CoordinationType$1.POINT_LAYER, coordinationScopes);
|
|
@@ -271364,7 +271850,9 @@ function NeuroglancerSubscriber(props) {
|
|
|
271364
271850
|
CoordinationType$1.OBS_HIGHLIGHT,
|
|
271365
271851
|
CoordinationType$1.TOOLTIPS_VISIBLE,
|
|
271366
271852
|
CoordinationType$1.TOOLTIP_CROSSHAIRS_VISIBLE,
|
|
271367
|
-
CoordinationType$1.LEGEND_VISIBLE
|
|
271853
|
+
CoordinationType$1.LEGEND_VISIBLE,
|
|
271854
|
+
CoordinationType$1.FEATURE_TYPE,
|
|
271855
|
+
CoordinationType$1.FEATURE_VALUE_TYPE
|
|
271368
271856
|
], coordinationScopes, coordinationScopesBy, CoordinationType$1.SEGMENTATION_LAYER, CoordinationType$1.SEGMENTATION_CHANNEL);
|
|
271369
271857
|
const pointLayerCoordination = useComplexCoordination([
|
|
271370
271858
|
CoordinationType$1.OBS_TYPE,
|
|
@@ -271381,7 +271869,10 @@ function NeuroglancerSubscriber(props) {
|
|
|
271381
271869
|
CoordinationType$1.TOOLTIPS_VISIBLE,
|
|
271382
271870
|
CoordinationType$1.TOOLTIP_CROSSHAIRS_VISIBLE,
|
|
271383
271871
|
CoordinationType$1.LEGEND_VISIBLE,
|
|
271384
|
-
CoordinationType$1.SPATIAL_POINT_STROKE_WIDTH
|
|
271872
|
+
CoordinationType$1.SPATIAL_POINT_STROKE_WIDTH,
|
|
271873
|
+
CoordinationType$1.OBS_SET_COLOR,
|
|
271874
|
+
CoordinationType$1.OBS_SET_SELECTION,
|
|
271875
|
+
CoordinationType$1.ADDITIONAL_OBS_SETS
|
|
271385
271876
|
], coordinationScopes, coordinationScopesBy, CoordinationType$1.POINT_LAYER);
|
|
271386
271877
|
const [obsPointsData, obsPointsDataStatus, obsPointsUrls, obsPointsErrors] = useMultiObsPoints(coordinationScopes, coordinationScopesBy, loaders, dataset, mergeCoordination, uuid2);
|
|
271387
271878
|
const [pointMultiIndicesData, pointMultiIndicesDataStatus, pointMultiIndicesDataErrors] = usePointMultiObsFeatureMatrixIndices(coordinationScopes, coordinationScopesBy, loaders, dataset);
|
|
@@ -271407,34 +271898,89 @@ function NeuroglancerSubscriber(props) {
|
|
|
271407
271898
|
segmentationMultiFeatureSelectionStatus,
|
|
271408
271899
|
segmentationMultiIndicesDataStatus
|
|
271409
271900
|
]);
|
|
271410
|
-
const
|
|
271901
|
+
const lastVitessceRotationRef = useRef({
|
|
271902
|
+
x: spatialRotationX,
|
|
271903
|
+
y: spatialRotationY,
|
|
271904
|
+
z: spatialRotationZ,
|
|
271905
|
+
orbit: spatialRotationOrbit
|
|
271906
|
+
});
|
|
271907
|
+
const prevCoordsRef = useRef({
|
|
271908
|
+
zoom: spatialZoom,
|
|
271909
|
+
rx: spatialRotationX,
|
|
271910
|
+
ry: spatialRotationY,
|
|
271911
|
+
rz: spatialRotationZ,
|
|
271912
|
+
orbit: spatialRotationOrbit,
|
|
271913
|
+
tx: spatialTargetX,
|
|
271914
|
+
ty: spatialTargetY
|
|
271915
|
+
});
|
|
271411
271916
|
const segmentationColorMapping = useMemoCustomComparison(() => {
|
|
271412
271917
|
const result = {};
|
|
271413
271918
|
segmentationLayerScopes?.forEach((layerScope) => {
|
|
271414
271919
|
result[layerScope] = {};
|
|
271415
271920
|
segmentationChannelScopesByLayer?.[layerScope]?.forEach((channelScope) => {
|
|
271416
|
-
const { obsSets: layerSets, obsIndex:
|
|
271417
|
-
const
|
|
271921
|
+
const { obsSets: layerSets, obsIndex: layerIndexFromSets } = obsSegmentationsSetsData?.[layerScope]?.[channelScope] || {};
|
|
271922
|
+
const layerIndex = layerIndexFromSets ?? null;
|
|
271923
|
+
const { obsSetColor, obsColorEncoding, obsSetSelection, additionalObsSets, spatialChannelColor, spatialChannelOpacity, featureValueColormap, featureValueColormapRange } = segmentationChannelCoordination[0][layerScope][channelScope];
|
|
271418
271924
|
if (obsColorEncoding === "spatialChannelColor") {
|
|
271419
|
-
if (
|
|
271925
|
+
if (spatialChannelColor) {
|
|
271420
271926
|
const hex2 = rgbToHex$1(spatialChannelColor);
|
|
271421
271927
|
const ngCellColors = {};
|
|
271422
|
-
if (
|
|
271423
|
-
|
|
271424
|
-
|
|
271425
|
-
|
|
271426
|
-
|
|
271427
|
-
|
|
271428
|
-
|
|
271429
|
-
|
|
271430
|
-
|
|
271431
|
-
|
|
271928
|
+
if (layerIndex) {
|
|
271929
|
+
if (obsSetSelection?.length > 0) {
|
|
271930
|
+
const mergedCellSets = mergeObsSets(layerSets, additionalObsSets);
|
|
271931
|
+
const selectedIds = /* @__PURE__ */ new Set();
|
|
271932
|
+
obsSetSelection.forEach((setPath) => {
|
|
271933
|
+
const rootNode = mergedCellSets?.tree?.find((n3) => n3.name === setPath[0]);
|
|
271934
|
+
const leafNode = setPath.length > 1 ? rootNode?.children?.find((n3) => n3.name === setPath[1]) : rootNode;
|
|
271935
|
+
leafNode?.set?.forEach(([id2]) => selectedIds.add(String(id2)));
|
|
271936
|
+
});
|
|
271937
|
+
layerIndex.forEach((id2) => {
|
|
271938
|
+
if (selectedIds.has(String(id2))) {
|
|
271939
|
+
ngCellColors[id2] = hex2;
|
|
271940
|
+
}
|
|
271941
|
+
});
|
|
271942
|
+
} else {
|
|
271943
|
+
layerIndex.forEach((id2) => {
|
|
271432
271944
|
ngCellColors[id2] = hex2;
|
|
271433
|
-
}
|
|
271434
|
-
}
|
|
271945
|
+
});
|
|
271946
|
+
}
|
|
271435
271947
|
}
|
|
271436
|
-
result[layerScope][channelScope] = ngCellColors;
|
|
271948
|
+
result[layerScope][channelScope] = remapCellColors(ngCellColors, cellIdToMeshIdRef);
|
|
271949
|
+
result[layerScope].opacity = spatialChannelOpacity ?? 1;
|
|
271950
|
+
result[layerScope].defaultColor = hex2;
|
|
271951
|
+
}
|
|
271952
|
+
} else if (obsColorEncoding === "geneSelection") {
|
|
271953
|
+
const instanceObsIndex = obsSegmentationsSetsData?.[layerScope]?.[channelScope]?.obsIndex;
|
|
271954
|
+
const matrixObsIndex = segmentationMultiIndicesData?.[layerScope]?.[channelScope]?.obsIndex;
|
|
271955
|
+
const expressionData = segmentationMultiExpressionNormData?.[layerScope]?.[channelScope];
|
|
271956
|
+
if (instanceObsIndex && matrixObsIndex && expressionData?.[0]) {
|
|
271957
|
+
const matrixIndexMap = new Map(matrixObsIndex.map((key2, i2) => {
|
|
271958
|
+
const normalizedKey = key2.replace(/^.*_/, "");
|
|
271959
|
+
return [normalizedKey, i2];
|
|
271960
|
+
}));
|
|
271961
|
+
const toMatrixIndex = instanceObsIndex.map((key2) => matrixIndexMap.get(String(key2)));
|
|
271962
|
+
const [low, high] = featureValueColormapRange ?? [0, 1];
|
|
271963
|
+
const ngCellColors = {};
|
|
271964
|
+
instanceObsIndex.forEach((id2, i2) => {
|
|
271965
|
+
const rowIndex = toMatrixIndex[i2];
|
|
271966
|
+
const rawVal = expressionData[0][rowIndex] ?? 0;
|
|
271967
|
+
const t4 = rawVal / 255;
|
|
271968
|
+
const tScaled = (t4 - low) / Math.max(high - low, 1e-4);
|
|
271969
|
+
const tClamped = Math.max(0, Math.min(1, tScaled));
|
|
271970
|
+
const color2 = applyColormap(featureValueColormap ?? "viridis", tClamped);
|
|
271971
|
+
ngCellColors[id2] = rgbToHex$1(color2);
|
|
271972
|
+
});
|
|
271973
|
+
result[layerScope][channelScope] = remapCellColors(ngCellColors, cellIdToMeshIdRef);
|
|
271437
271974
|
result[layerScope].opacity = spatialChannelOpacity ?? 1;
|
|
271975
|
+
} else if (instanceObsIndex) {
|
|
271976
|
+
const fallbackColor = spatialChannelColor ? rgbToHex$1(spatialChannelColor) : GREY_HEX;
|
|
271977
|
+
const ngCellColors = {};
|
|
271978
|
+
instanceObsIndex.forEach((id2) => {
|
|
271979
|
+
ngCellColors[id2] = fallbackColor;
|
|
271980
|
+
});
|
|
271981
|
+
result[layerScope][channelScope] = remapCellColors(ngCellColors, cellIdToMeshIdRef);
|
|
271982
|
+
result[layerScope].opacity = spatialChannelOpacity ?? 1;
|
|
271983
|
+
result[layerScope].defaultColor = fallbackColor;
|
|
271438
271984
|
}
|
|
271439
271985
|
} else if (layerSets && layerIndex) {
|
|
271440
271986
|
const mergedCellSets = mergeObsSets(layerSets, additionalObsSets);
|
|
@@ -271446,10 +271992,10 @@ function NeuroglancerSubscriber(props) {
|
|
|
271446
271992
|
theme
|
|
271447
271993
|
});
|
|
271448
271994
|
const ngCellColors = {};
|
|
271449
|
-
cellColors.forEach((color2,
|
|
271450
|
-
ngCellColors[
|
|
271995
|
+
cellColors.forEach((color2, id2) => {
|
|
271996
|
+
ngCellColors[id2] = rgbToHex$1(color2);
|
|
271451
271997
|
});
|
|
271452
|
-
result[layerScope][channelScope] = ngCellColors;
|
|
271998
|
+
result[layerScope][channelScope] = remapCellColors(ngCellColors, cellIdToMeshIdRef);
|
|
271453
271999
|
result[layerScope].opacity = spatialChannelOpacity ?? 1;
|
|
271454
272000
|
}
|
|
271455
272001
|
});
|
|
@@ -271462,14 +272008,201 @@ function NeuroglancerSubscriber(props) {
|
|
|
271462
272008
|
segmentationChannelScopesByLayer,
|
|
271463
272009
|
obsSegmentationsSetsData,
|
|
271464
272010
|
segmentationChannelCoordination,
|
|
271465
|
-
theme
|
|
272011
|
+
theme,
|
|
272012
|
+
segmentationMultiExpressionNormData,
|
|
272013
|
+
segmentationMultiIndicesData,
|
|
272014
|
+
csvLoaded
|
|
271466
272015
|
}, customIsEqualForCellColors);
|
|
271467
|
-
const
|
|
272016
|
+
const initialViewerState = useNeuroglancerViewerState(theme, showAxisLines, segmentationLayerScopes, segmentationChannelScopesByLayer, segmentationLayerCoordination, segmentationChannelCoordination, obsSegmentationsUrls, obsSegmentationsData, pointLayerScopes, pointLayerCoordination, obsPointsUrls, obsPointsData, pointMultiIndicesData);
|
|
271468
272017
|
const [latestViewerStateIteration, incrementLatestViewerStateIteration] = useReducer((x2) => x2 + 1, 0);
|
|
271469
272018
|
const latestViewerStateRef = useRef({
|
|
271470
|
-
...
|
|
272019
|
+
...initialViewerState,
|
|
271471
272020
|
...initialNgCameraState ?? {}
|
|
271472
272021
|
});
|
|
272022
|
+
useEffect(() => {
|
|
272023
|
+
if (!csvUrl)
|
|
272024
|
+
return;
|
|
272025
|
+
fetch(csvUrl).then((r3) => r3.text()).then((text2) => {
|
|
272026
|
+
const lines = text2.split("\n");
|
|
272027
|
+
const header = lines[0].split(",");
|
|
272028
|
+
const meshIdIdx = header.indexOf("MeshID");
|
|
272029
|
+
const cellIdIdx = header.indexOf("CellID");
|
|
272030
|
+
const meshMap = {};
|
|
272031
|
+
const cellMap = {};
|
|
272032
|
+
lines.slice(1).forEach((l2) => {
|
|
272033
|
+
const cols = l2.split(",");
|
|
272034
|
+
const meshId = cols[meshIdIdx]?.trim();
|
|
272035
|
+
const cellId = cols[cellIdIdx]?.trim();
|
|
272036
|
+
if (meshId && cellId) {
|
|
272037
|
+
meshMap[meshId] = cellId;
|
|
272038
|
+
cellMap[cellId] = meshId;
|
|
272039
|
+
}
|
|
272040
|
+
});
|
|
272041
|
+
meshIdToCellIdRef.current = meshMap;
|
|
272042
|
+
cellIdToMeshIdRef.current = cellMap;
|
|
272043
|
+
setCsvLoaded(true);
|
|
272044
|
+
});
|
|
272045
|
+
}, [csvUrl]);
|
|
272046
|
+
useEffect(() => {
|
|
272047
|
+
chunkCacheRef.current.clear();
|
|
272048
|
+
}, [obsPointsData]);
|
|
272049
|
+
useEffect(() => {
|
|
272050
|
+
if (ngWidth && ngHeight) {
|
|
272051
|
+
viewportSizeRef.current = { width: ngWidth, height: ngHeight };
|
|
272052
|
+
}
|
|
272053
|
+
}, [ngWidth, ngHeight]);
|
|
272054
|
+
const setContainerNode = useCallback((node2) => {
|
|
272055
|
+
containerRef.current = node2;
|
|
272056
|
+
if (resizeObserverRef.current) {
|
|
272057
|
+
resizeObserverRef.current.disconnect();
|
|
272058
|
+
resizeObserverRef.current = null;
|
|
272059
|
+
}
|
|
272060
|
+
if (node2) {
|
|
272061
|
+
const rect2 = node2.getBoundingClientRect();
|
|
272062
|
+
if (rect2.width && rect2.height) {
|
|
272063
|
+
viewportSizeRef.current = { width: rect2.width, height: rect2.height };
|
|
272064
|
+
}
|
|
272065
|
+
const observer2 = new ResizeObserver((entries2) => {
|
|
272066
|
+
const entry2 = entries2[0];
|
|
272067
|
+
if (!entry2)
|
|
272068
|
+
return;
|
|
272069
|
+
const { width: width2, height: height2 } = entry2.contentRect;
|
|
272070
|
+
if (width2 && height2) {
|
|
272071
|
+
viewportSizeRef.current = { width: width2, height: height2 };
|
|
272072
|
+
}
|
|
272073
|
+
});
|
|
272074
|
+
observer2.observe(node2);
|
|
272075
|
+
resizeObserverRef.current = observer2;
|
|
272076
|
+
}
|
|
272077
|
+
}, []);
|
|
272078
|
+
const updateVisibleSegments = useCallback(async () => {
|
|
272079
|
+
if (!annotationInfoRef.current)
|
|
272080
|
+
return;
|
|
272081
|
+
if (!annotationTransformRef.current)
|
|
272082
|
+
return;
|
|
272083
|
+
if (!segmentationLayerScopes?.length)
|
|
272084
|
+
return;
|
|
272085
|
+
if (!pointLayerScopes?.length)
|
|
272086
|
+
return;
|
|
272087
|
+
const { position: position2, projectionScale } = latestViewerStateRef.current;
|
|
272088
|
+
if (!position2 || !projectionScale)
|
|
272089
|
+
return;
|
|
272090
|
+
const maxProjectionScale = meshLoadProjectionScaleThreshold ?? MESH_LOAD_THRESHOLD;
|
|
272091
|
+
if (projectionScale > maxProjectionScale) {
|
|
272092
|
+
if (visibleSegmentIdsRef.current?.length !== 0) {
|
|
272093
|
+
visibleSegmentIdsRef.current = [];
|
|
272094
|
+
incrementLatestViewerStateIteration();
|
|
272095
|
+
setIsMeshLoading(false);
|
|
272096
|
+
}
|
|
272097
|
+
return;
|
|
272098
|
+
}
|
|
272099
|
+
const { width: width2, height: height2 } = viewportSizeRef.current;
|
|
272100
|
+
if (!width2 || !height2)
|
|
272101
|
+
return;
|
|
272102
|
+
const transform3 = annotationTransformRef.current;
|
|
272103
|
+
const info2 = annotationInfoRef.current;
|
|
272104
|
+
const cellsUrl2 = info2.url;
|
|
272105
|
+
const allLevelCoords = info2.spatial.flatMap((level) => {
|
|
272106
|
+
const [gx, gy, gz] = level.grid_shape;
|
|
272107
|
+
const coords = [];
|
|
272108
|
+
for (let cx = 0; cx < gx; cx++) {
|
|
272109
|
+
for (let cy = 0; cy < gy; cy++) {
|
|
272110
|
+
for (let cz = 0; cz < gz; cz++) {
|
|
272111
|
+
coords.push({ level: level.key, cx, cy, cz });
|
|
272112
|
+
}
|
|
272113
|
+
}
|
|
272114
|
+
}
|
|
272115
|
+
return coords;
|
|
272116
|
+
});
|
|
272117
|
+
const fetchChunkWithPositions = async ({ level, cx, cy, cz }) => {
|
|
272118
|
+
const { serializers, serializer: defaultSerializer } = annotationTransformRef.current;
|
|
272119
|
+
const serializer2 = serializers?.[0] ?? defaultSerializer;
|
|
272120
|
+
if (!serializer2)
|
|
272121
|
+
return [];
|
|
272122
|
+
const cacheKey = `${cellsUrl2}/${level}/${cx}_${cy}_${cz}`;
|
|
272123
|
+
if (chunkCacheRef.current.has(cacheKey)) {
|
|
272124
|
+
return chunkCacheRef.current.get(cacheKey);
|
|
272125
|
+
}
|
|
272126
|
+
try {
|
|
272127
|
+
const res = await fetch(cacheKey);
|
|
272128
|
+
if (!res.ok) {
|
|
272129
|
+
chunkCacheRef.current.set(cacheKey, []);
|
|
272130
|
+
return [];
|
|
272131
|
+
}
|
|
272132
|
+
const buffer2 = await res.arrayBuffer();
|
|
272133
|
+
const entries2 = parseAnnotationChunkSegmentsWithPositions(buffer2, serializer2);
|
|
272134
|
+
chunkCacheRef.current.set(cacheKey, entries2);
|
|
272135
|
+
return entries2;
|
|
272136
|
+
} catch (e3) {
|
|
272137
|
+
chunkCacheRef.current.set(cacheKey, []);
|
|
272138
|
+
return [];
|
|
272139
|
+
}
|
|
272140
|
+
};
|
|
272141
|
+
try {
|
|
272142
|
+
const results = await Promise.all(allLevelCoords.map(fetchChunkWithPositions));
|
|
272143
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
272144
|
+
const allEntries = results.flat().filter(({ id: id2 }) => {
|
|
272145
|
+
if (seenIds.has(id2))
|
|
272146
|
+
return false;
|
|
272147
|
+
seenIds.add(id2);
|
|
272148
|
+
return true;
|
|
272149
|
+
});
|
|
272150
|
+
const obsIdToMeshId = {};
|
|
272151
|
+
allEntries.forEach(({ id: id2, obsId }) => {
|
|
272152
|
+
obsIdToMeshId[obsId] = id2;
|
|
272153
|
+
});
|
|
272154
|
+
obsIdToMeshIdRef.current = obsIdToMeshId;
|
|
272155
|
+
const mat = getViewProjectionMatRef.current?.();
|
|
272156
|
+
let visibleIds;
|
|
272157
|
+
if (!mat) {
|
|
272158
|
+
console.warn("No viewProjectionMatrix, loading all");
|
|
272159
|
+
visibleIds = [...new Set(allEntries.map(({ id: id2 }) => id2))];
|
|
272160
|
+
} else {
|
|
272161
|
+
const margin2 = Math.max(width2, height2) * 0.5;
|
|
272162
|
+
visibleIds = [...new Set(allEntries.filter(({ x: x2, y: y2, z: z2 }) => {
|
|
272163
|
+
const vx = x2 / transform3.x;
|
|
272164
|
+
const vy = y2 / transform3.y;
|
|
272165
|
+
const vz = (z2 || 0) / transform3.z;
|
|
272166
|
+
const cx = mat[0] * vx + mat[4] * vy + mat[8] * vz + mat[12];
|
|
272167
|
+
const cy = mat[1] * vx + mat[5] * vy + mat[9] * vz + mat[13];
|
|
272168
|
+
const cw2 = mat[3] * vx + mat[7] * vy + mat[11] * vz + mat[15];
|
|
272169
|
+
const screenX = (cx / cw2 + 1) * 0.5 * width2;
|
|
272170
|
+
const screenY = (1 - cy / cw2) * 0.5 * height2;
|
|
272171
|
+
return screenX >= -margin2 && screenX <= width2 + margin2 && screenY >= -margin2 && screenY <= height2 + margin2;
|
|
272172
|
+
}).map(({ id: id2 }) => id2))];
|
|
272173
|
+
}
|
|
272174
|
+
if (visibleIds.length === 0) {
|
|
272175
|
+
if (visibleSegmentIdsRef.current?.length !== 0) {
|
|
272176
|
+
visibleSegmentIdsRef.current = [];
|
|
272177
|
+
incrementLatestViewerStateIteration();
|
|
272178
|
+
}
|
|
272179
|
+
setIsMeshLoading(false);
|
|
272180
|
+
return;
|
|
272181
|
+
}
|
|
272182
|
+
const prevIds = new Set(visibleSegmentIdsRef.current ?? []);
|
|
272183
|
+
const addedIdsCount = visibleIds.filter((id2) => !prevIds.has(id2)).length;
|
|
272184
|
+
const hasSignificantChange = addedIdsCount > 20;
|
|
272185
|
+
if (hasSignificantChange && visibleIds.length > 0) {
|
|
272186
|
+
setIsMeshLoading(true);
|
|
272187
|
+
}
|
|
272188
|
+
const prevSorted = [...visibleSegmentIdsRef.current ?? []].sort().join(",");
|
|
272189
|
+
const nextSorted = [...visibleIds].sort().join(",");
|
|
272190
|
+
if (prevSorted !== nextSorted) {
|
|
272191
|
+
visibleSegmentIdsRef.current = visibleIds;
|
|
272192
|
+
incrementLatestViewerStateIteration();
|
|
272193
|
+
}
|
|
272194
|
+
if (hasSignificantChange) {
|
|
272195
|
+
setTimeout(() => setIsMeshLoading(false), MESH_LOADING_OVERLAY_TIMEOUT);
|
|
272196
|
+
}
|
|
272197
|
+
} catch (e3) {
|
|
272198
|
+
console.warn("[updateVisibleSegments] error:", e3);
|
|
272199
|
+
setIsMeshLoading(false);
|
|
272200
|
+
}
|
|
272201
|
+
}, [segmentationLayerScopes, pointLayerScopes, obsPointsData, meshLoadProjectionScaleThreshold]);
|
|
272202
|
+
useEffect(() => {
|
|
272203
|
+
updateVisibleSegmentsThrottledRef.current = throttle$1(updateVisibleSegments, 500);
|
|
272204
|
+
return () => updateVisibleSegmentsThrottledRef.current?.cancel();
|
|
272205
|
+
}, [updateVisibleSegments]);
|
|
271473
272206
|
useEffect(() => {
|
|
271474
272207
|
const prevNgCameraState = {
|
|
271475
272208
|
position: latestViewerStateRef.current.position,
|
|
@@ -271477,37 +272210,50 @@ function NeuroglancerSubscriber(props) {
|
|
|
271477
272210
|
projectionScale: latestViewerStateRef.current.projectionScale
|
|
271478
272211
|
};
|
|
271479
272212
|
latestViewerStateRef.current = {
|
|
271480
|
-
...
|
|
272213
|
+
...initialViewerState,
|
|
271481
272214
|
...prevNgCameraState
|
|
271482
272215
|
};
|
|
271483
272216
|
incrementLatestViewerStateIteration();
|
|
271484
|
-
}, [
|
|
271485
|
-
const
|
|
271486
|
-
|
|
271487
|
-
|
|
271488
|
-
|
|
271489
|
-
const
|
|
271490
|
-
|
|
271491
|
-
|
|
271492
|
-
|
|
271493
|
-
|
|
271494
|
-
|
|
271495
|
-
|
|
271496
|
-
|
|
271497
|
-
|
|
271498
|
-
|
|
271499
|
-
|
|
271500
|
-
|
|
271501
|
-
|
|
271502
|
-
|
|
271503
|
-
|
|
271504
|
-
|
|
271505
|
-
|
|
271506
|
-
|
|
271507
|
-
|
|
271508
|
-
|
|
271509
|
-
|
|
271510
|
-
|
|
272217
|
+
}, [initialViewerState]);
|
|
272218
|
+
const cellsUrl = useMemo$1(() => {
|
|
272219
|
+
const firstScope = pointLayerScopes?.[0];
|
|
272220
|
+
return obsPointsUrls?.[firstScope]?.[0]?.url ?? null;
|
|
272221
|
+
}, [pointLayerScopes, obsPointsUrls]);
|
|
272222
|
+
const hasMatchingAnnotationSource = useMemo$1(() => {
|
|
272223
|
+
if (!cellsUrl)
|
|
272224
|
+
return false;
|
|
272225
|
+
const firstPointScope = pointLayerScopes?.[0];
|
|
272226
|
+
return pointsHaveMatchingSegmentation({
|
|
272227
|
+
pointObsType: pointLayerCoordination[0]?.[firstPointScope]?.obsType,
|
|
272228
|
+
segmentationLayerScopes,
|
|
272229
|
+
segmentationChannelScopesByLayer,
|
|
272230
|
+
segmentationChannelCoordination
|
|
272231
|
+
});
|
|
272232
|
+
}, [cellsUrl, pointLayerScopes, segmentationLayerScopes, segmentationChannelScopesByLayer]);
|
|
272233
|
+
useEffect(() => {
|
|
272234
|
+
if (!cellsUrl)
|
|
272235
|
+
return;
|
|
272236
|
+
fetch(`${cellsUrl}/info`).then((r3) => r3.json()).then((info2) => {
|
|
272237
|
+
const infoWithUrl = {
|
|
272238
|
+
...info2,
|
|
272239
|
+
url: cellsUrl
|
|
272240
|
+
};
|
|
272241
|
+
annotationInfoRef.current = infoWithUrl;
|
|
272242
|
+
if (annotationTransformRef.current)
|
|
272243
|
+
setAnnotationReady(true);
|
|
272244
|
+
}).catch((err2) => console.error("failed to fetch annotation info:", err2));
|
|
272245
|
+
}, [cellsUrl]);
|
|
272246
|
+
useEffect(() => {
|
|
272247
|
+
if (annotationReady) {
|
|
272248
|
+
setIsLayersLoaded(true);
|
|
272249
|
+
updateVisibleSegments();
|
|
272250
|
+
}
|
|
272251
|
+
}, [annotationReady]);
|
|
272252
|
+
const onAnnotationSourceReady = useCallback((transform3) => {
|
|
272253
|
+
annotationTransformRef.current = transform3;
|
|
272254
|
+
if (annotationInfoRef.current)
|
|
272255
|
+
setAnnotationReady(true);
|
|
272256
|
+
}, []);
|
|
271511
272257
|
const handleStateUpdate = useCallback((newState) => {
|
|
271512
272258
|
lastInteractionSource.current = LAST_INTERACTION_SOURCE.neuroglancer;
|
|
271513
272259
|
const { projectionScale, projectionOrientation, position: position2 } = newState;
|
|
@@ -271540,6 +272286,7 @@ function NeuroglancerSubscriber(props) {
|
|
|
271540
272286
|
setZoom(vitZoomFromNg);
|
|
271541
272287
|
zoomRafRef.current = null;
|
|
271542
272288
|
});
|
|
272289
|
+
updateVisibleSegments();
|
|
271543
272290
|
}
|
|
271544
272291
|
lastNgScaleRef.current = projectionScale;
|
|
271545
272292
|
}
|
|
@@ -271580,7 +272327,8 @@ function NeuroglancerSubscriber(props) {
|
|
|
271580
272327
|
projectionScale,
|
|
271581
272328
|
position: position2
|
|
271582
272329
|
};
|
|
271583
|
-
|
|
272330
|
+
updateVisibleSegmentsThrottledRef.current?.();
|
|
272331
|
+
}, [updateVisibleSegmentsThrottledRef]);
|
|
271584
272332
|
const onSegmentClick = useCallback((value2) => {
|
|
271585
272333
|
if (value2) {
|
|
271586
272334
|
const id2 = String(value2);
|
|
@@ -271605,11 +272353,18 @@ function NeuroglancerSubscriber(props) {
|
|
|
271605
272353
|
const channelScope = segmentationChannelScopesByLayer?.[layerScope]?.[0];
|
|
271606
272354
|
result[layerScope] = {
|
|
271607
272355
|
colors: segmentationColorMapping?.[layerScope]?.[channelScope] ?? {},
|
|
271608
|
-
opacity: segmentationColorMapping?.[layerScope]?.opacity ?? 1
|
|
272356
|
+
opacity: segmentationColorMapping?.[layerScope]?.opacity ?? 1,
|
|
272357
|
+
defaultColor: segmentationColorMapping?.[layerScope]?.defaultColor ?? null
|
|
271609
272358
|
};
|
|
271610
272359
|
});
|
|
271611
272360
|
return result;
|
|
271612
272361
|
}, [segmentationColorMapping, segmentationLayerScopes, segmentationChannelScopesByLayer]);
|
|
272362
|
+
useEffect(() => {
|
|
272363
|
+
if (!hasMatchingAnnotationSource && isReady && !segmentationLayerScopes?.length) {
|
|
272364
|
+
setIsLayersLoaded(true);
|
|
272365
|
+
}
|
|
272366
|
+
}, [hasMatchingAnnotationSource, isReady, segmentationLayerScopes]);
|
|
272367
|
+
const meshOpacity = hasMatchingAnnotationSource ? MESH_OPACITY : void 0;
|
|
271613
272368
|
const derivedViewerState = useMemo$1(() => {
|
|
271614
272369
|
const { current: current2 } = latestViewerStateRef;
|
|
271615
272370
|
if (current2.layers.length <= 0) {
|
|
@@ -271668,13 +272423,33 @@ function NeuroglancerSubscriber(props) {
|
|
|
271668
272423
|
lastInteractionSource.current = null;
|
|
271669
272424
|
}
|
|
271670
272425
|
const updatedLayers = current2?.layers?.map((layer, idx) => {
|
|
271671
|
-
|
|
272426
|
+
if (layer.type !== "segmentation")
|
|
272427
|
+
return layer;
|
|
272428
|
+
const layerScope = segmentationLayerScopes?.find((scope) => layer.name?.includes(scope));
|
|
272429
|
+
if (!layerScope)
|
|
272430
|
+
return layer;
|
|
271672
272431
|
const layerColorMapping = cellColorMappingByLayer?.[layerScope]?.colors ?? {};
|
|
271673
|
-
const
|
|
272432
|
+
const defaultColor = cellColorMappingByLayer?.[layerScope]?.defaultColor;
|
|
272433
|
+
let segments2 = [];
|
|
272434
|
+
if (hasMatchingAnnotationSource) {
|
|
272435
|
+
segments2 = visibleSegmentIdsRef.current ?? [];
|
|
272436
|
+
} else if (Object.keys(layerColorMapping).length > 0) {
|
|
272437
|
+
segments2 = Object.keys(layerColorMapping);
|
|
272438
|
+
}
|
|
272439
|
+
let derivedSegmentColors = {};
|
|
272440
|
+
if (hasMatchingAnnotationSource && segments2.length > 0) {
|
|
272441
|
+
segments2.forEach((meshId) => {
|
|
272442
|
+
const color2 = layerColorMapping[meshId] || defaultColor;
|
|
272443
|
+
if (color2)
|
|
272444
|
+
derivedSegmentColors[meshId] = color2;
|
|
272445
|
+
});
|
|
272446
|
+
} else if (!hasMatchingAnnotationSource) {
|
|
272447
|
+
derivedSegmentColors = layerColorMapping;
|
|
272448
|
+
}
|
|
271674
272449
|
return {
|
|
271675
272450
|
...layer,
|
|
271676
|
-
segments:
|
|
271677
|
-
segmentColors:
|
|
272451
|
+
segments: segments2,
|
|
272452
|
+
segmentColors: derivedSegmentColors,
|
|
271678
272453
|
objectAlpha: cellColorMappingByLayer?.[layerScope]?.opacity ?? 1
|
|
271679
272454
|
};
|
|
271680
272455
|
}) ?? [];
|
|
@@ -271704,17 +272479,21 @@ function NeuroglancerSubscriber(props) {
|
|
|
271704
272479
|
spatialRotationZ,
|
|
271705
272480
|
spatialTargetX,
|
|
271706
272481
|
spatialTargetY,
|
|
271707
|
-
|
|
271708
|
-
latestViewerStateIteration
|
|
272482
|
+
initialViewerState,
|
|
272483
|
+
latestViewerStateIteration,
|
|
272484
|
+
hasMatchingAnnotationSource
|
|
271709
272485
|
]);
|
|
271710
272486
|
const onSegmentHighlight = useCallback((obsId) => {
|
|
271711
272487
|
setCellHighlight(String(obsId));
|
|
271712
272488
|
}, [setCellHighlight]);
|
|
271713
272489
|
const handleLayerLoadingChange = useCallback((isLoaded) => {
|
|
271714
|
-
|
|
271715
|
-
|
|
272490
|
+
if (!isLayersLoaded && isLoaded) {
|
|
272491
|
+
setIsLayersLoaded(true);
|
|
272492
|
+
}
|
|
272493
|
+
}, [isLayersLoaded]);
|
|
271716
272494
|
const hasLayers = derivedViewerState?.layers?.length > 0;
|
|
271717
|
-
|
|
272495
|
+
const showPointsLegend = !hasMatchingAnnotationSource;
|
|
272496
|
+
return jsx$1(TitleInfo, { title: title2, info: subtitle, helpText, isSpatial: true, theme, closeButtonVisible, downloadButtonVisible, removeGridComponent, isReady: isReady && isLayersLoaded, errors, withPadding: false, guideUrl: GUIDE_URL, children: hasLayers ? jsxs("div", { style: { position: "relative", width: "100%", height: "100%" }, ref: setContainerNode, children: [jsx$1("div", { style: { position: "absolute", top: 0, right: 0, zIndex: 50 }, children: jsx$1(MultiLegend, {
|
|
271718
272497
|
theme: "dark",
|
|
271719
272498
|
maxHeight: ngHeight,
|
|
271720
272499
|
// Segmentations
|
|
@@ -271723,10 +272502,12 @@ function NeuroglancerSubscriber(props) {
|
|
|
271723
272502
|
segmentationChannelScopesByLayer,
|
|
271724
272503
|
segmentationChannelCoordination,
|
|
271725
272504
|
// Points
|
|
271726
|
-
pointLayerScopes,
|
|
272505
|
+
pointLayerScopes: showPointsLegend ? pointLayerScopes : void 0,
|
|
271727
272506
|
pointLayerCoordination,
|
|
271728
272507
|
pointMultiIndicesData
|
|
271729
|
-
}) }), jsx$1(NeuroglancerComp, { classes: classes2, onSegmentClick, onSelectHoveredCoords: onSegmentHighlight, viewerState: derivedViewerState, cellColorMapping: cellColorMappingByLayer, setViewerState: handleStateUpdate, onLayerLoadingChange: handleLayerLoadingChange
|
|
272508
|
+
}) }), isMeshLoading ? jsx$1(Chip, { label: "Loading meshes...", size: "small", color: "primary", className: classes2.meshLoadingIndicator }) : null, jsx$1(NeuroglancerComp, { classes: classes2, onSegmentClick, onSelectHoveredCoords: onSegmentHighlight, viewerState: derivedViewerState, cellColorMapping: cellColorMappingByLayer, setViewerState: handleStateUpdate, onLayerLoadingChange: handleLayerLoadingChange, onAnnotationSourceReady, onViewerReady: (getFn) => {
|
|
272509
|
+
getViewProjectionMatRef.current = getFn;
|
|
272510
|
+
}, getMeshIdToCellId: (meshId) => meshIdToCellIdRef.current[meshId], cellsUrl, meshOpacity })] }) : null });
|
|
271730
272511
|
}
|
|
271731
272512
|
const FEATURE_AGGREGATION_STRATEGIES = ["first", "last", "sum", "mean"];
|
|
271732
272513
|
function CellSetExpressionPlotOptions(props) {
|
|
@@ -324224,7 +325005,7 @@ const VEGA_THEMES = {
|
|
|
324224
325005
|
};
|
|
324225
325006
|
const DATASET_NAME = "table";
|
|
324226
325007
|
function VegaGlobalStyles() {
|
|
324227
|
-
const { theme } = useStyles$
|
|
325008
|
+
const { theme } = useStyles$y();
|
|
324228
325009
|
return jsx$1(GlobalStyles$3, { styles: {
|
|
324229
325010
|
"#vg-tooltip-element.vg-tooltip.custom-theme": {
|
|
324230
325011
|
boxShadow: "0px 2px 4px -1px rgba(0,0,0,0.2),0px 4px 5px 0px rgba(0,0,0,0.14),0px 1px 10px 0px rgba(0,0,0,0.12)",
|
|
@@ -324258,7 +325039,7 @@ function renderTooltipContents(tooltipText) {
|
|
|
324258
325039
|
}
|
|
324259
325040
|
function VegaPlot(props) {
|
|
324260
325041
|
const { spec: partialSpec, data: data2, getTooltipText, signalListeners, renderer = "svg", onNewView } = props;
|
|
324261
|
-
const { classes: tooltipClasses2 } = useStyles$
|
|
325042
|
+
const { classes: tooltipClasses2 } = useStyles$t();
|
|
324262
325043
|
const tooltipHandler = useMemo$1(() => {
|
|
324263
325044
|
if (typeof getTooltipText === "function") {
|
|
324264
325045
|
const tooltipConfig = {
|
|
@@ -349548,7 +350329,7 @@ function Vitessce(props) {
|
|
|
349548
350329
|
);
|
|
349549
350330
|
}
|
|
349550
350331
|
export {
|
|
349551
|
-
|
|
350332
|
+
GREY_HEX as $,
|
|
349552
350333
|
require_descriptors as A,
|
|
349553
350334
|
BaseDecoder as B,
|
|
349554
350335
|
CoordinationType$1 as C,
|
|
@@ -349577,13 +350358,14 @@ export {
|
|
|
349577
350358
|
require_redefine as Z,
|
|
349578
350359
|
require_objectAssign as _,
|
|
349579
350360
|
getDefaultExportFromCjs$1 as a,
|
|
349580
|
-
|
|
349581
|
-
|
|
349582
|
-
|
|
349583
|
-
|
|
349584
|
-
|
|
349585
|
-
|
|
349586
|
-
|
|
350361
|
+
diffCameraState as a0,
|
|
350362
|
+
Vitessce as a1,
|
|
350363
|
+
PluginFileType as a2,
|
|
350364
|
+
PluginViewType as a3,
|
|
350365
|
+
PluginCoordinationType as a4,
|
|
350366
|
+
PluginJointFileType as a5,
|
|
350367
|
+
PluginAsyncFunction as a6,
|
|
350368
|
+
z as a7,
|
|
349587
350369
|
LercAddCompression as b,
|
|
349588
350370
|
commonjsGlobal$1 as c,
|
|
349589
350371
|
requireAssign as d,
|