@vitessce/neuroglancer 3.9.4 → 3.9.6

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.
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Generate a shader for spatialLayerColor encoding with no feature selection.
3
+ * All points get the static color.
4
+ * @param {[number, number, number]} staticColor RGB (0-255).
5
+ * @param {number} opacity Opacity (0-1).
6
+ * @returns {string} A GLSL shader string.
7
+ */
8
+ export function getSpatialLayerColorShader(staticColor: [number, number, number], opacity: number): string;
9
+ /**
10
+ * Generate a shader for spatialLayerColor encoding with feature selection.
11
+ * Selected features get the static color; unselected get the default color.
12
+ * @param {[number, number, number]} staticColor RGB (0-255).
13
+ * @param {number} opacity Opacity (0-1).
14
+ * @param {number[]} featureIndices Numeric indices of selected features.
15
+ * @param {[number, number, number]} defaultColor RGB (0-255) for unselected points.
16
+ * @param {string} featureIndexProp The property name for the feature index in the shader.
17
+ * @returns {string} A GLSL shader string.
18
+ */
19
+ export function getSpatialLayerColorWithSelectionShader(staticColor: [number, number, number], opacity: number, featureIndices: number[], defaultColor: [number, number, number], featureIndexProp: string): string;
20
+ /**
21
+ * Generate a shader for spatialLayerColor encoding with feature selection
22
+ * and featureFilterMode='featureSelection' (hide unselected points).
23
+ * @param {[number, number, number]} staticColor RGB (0-255).
24
+ * @param {number} opacity Opacity (0-1).
25
+ * @param {number[]} featureIndices Numeric indices of selected features.
26
+ * @param {string} featureIndexProp The property name for the feature index in the shader.
27
+ * @returns {string} A GLSL shader string.
28
+ */
29
+ export function getSpatialLayerColorFilteredShader(staticColor: [number, number, number], opacity: number, featureIndices: number[], featureIndexProp: string): string;
30
+ /**
31
+ * Generate a shader for geneSelection encoding with no feature selection.
32
+ * All points get the static color (since no features are selected to
33
+ * determine per-feature colors).
34
+ * @param {[number, number, number]} staticColor RGB (0-255).
35
+ * @param {number} opacity Opacity (0-1).
36
+ * @returns {string} A GLSL shader string.
37
+ */
38
+ export function getGeneSelectionNoSelectionShader(staticColor: [number, number, number], opacity: number): string;
39
+ /**
40
+ * Generate a shader for geneSelection encoding with feature selection.
41
+ * Each selected feature gets its color from featureColor; unselected
42
+ * points get the default color.
43
+ * @param {number[]} featureIndices Numeric indices of selected features.
44
+ * @param {[number, number, number][]} featureColors RGB (0-255) for each
45
+ * selected feature, in the same order as featureIndices.
46
+ * @param {[number, number, number]} staticColor Fallback RGB (0-255)
47
+ * for selected features without a specified color.
48
+ * @param {[number, number, number]} defaultColor RGB (0-255) for
49
+ * unselected points.
50
+ * @param {number} opacity Opacity (0-1).
51
+ * @param {string} featureIndexProp The property name for the feature index in the shader.
52
+ * @returns {string} A GLSL shader string.
53
+ */
54
+ export function getGeneSelectionWithSelectionShader(featureIndices: number[], featureColors: [number, number, number][], staticColor: [number, number, number], defaultColor: [number, number, number], opacity: number, featureIndexProp: string): string;
55
+ /**
56
+ * Generate a shader for geneSelection encoding with feature selection
57
+ * and featureFilterMode='featureSelection' (hide unselected points).
58
+ * @param {number[]} featureIndices Numeric indices of selected features.
59
+ * @param {[number, number, number][]} featureColors RGB (0-255) for each
60
+ * selected feature.
61
+ * @param {[number, number, number]} staticColor Fallback RGB (0-255).
62
+ * @param {number} opacity Opacity (0-1).
63
+ * @param {string} featureIndexProp The property name for the feature index in the shader.
64
+ * @returns {string} A GLSL shader string.
65
+ */
66
+ export function getGeneSelectionFilteredShader(featureIndices: number[], featureColors: [number, number, number][], staticColor: [number, number, number], opacity: number, featureIndexProp: string): string;
67
+ /**
68
+ * Generate a shader for randomByFeature encoding with no feature selection.
69
+ * Each feature gets a deterministic color from PALETTE based on its index.
70
+ * @param {number} opacity Opacity (0-1).
71
+ * @param {string} featureIndexProp The property name for the feature index in the shader.
72
+ * @returns {string} A GLSL shader string.
73
+ */
74
+ export function getRandomByFeatureShader(opacity: number, featureIndexProp: string): string;
75
+ /**
76
+ * Generate a shader for randomByFeature encoding with feature selection.
77
+ * Selected features get their deterministic palette color; unselected
78
+ * points get the default color.
79
+ * @param {number[]} featureIndices Numeric indices of selected features.
80
+ * @param {[number, number, number]} defaultColor RGB (0-255) for unselected.
81
+ * @param {number} opacity Opacity (0-1).
82
+ * @param {string} featureIndexProp The property name for the feature index in the shader.
83
+ * @returns {string} A GLSL shader string.
84
+ */
85
+ export function getRandomByFeatureWithSelectionShader(featureIndices: number[], defaultColor: [number, number, number], opacity: number, featureIndexProp: string): string;
86
+ /**
87
+ * Generate a shader for randomByFeature encoding with feature selection
88
+ * and featureFilterMode='featureSelection' (hide unselected points).
89
+ * @param {number[]} featureIndices Numeric indices of selected features.
90
+ * @param {number} opacity Opacity (0-1).
91
+ * @param {string} featureIndexProp The property name for the feature index in the shader.
92
+ * @returns {string} A GLSL shader string.
93
+ */
94
+ export function getRandomByFeatureFilteredShader(featureIndices: number[], opacity: number, featureIndexProp: string): string;
95
+ /**
96
+ * Generate a shader for random-per-point encoding with no feature selection.
97
+ * Each point gets a pseudo-random color based on its index.
98
+ * @param {number} opacity Opacity (0-1).
99
+ * @param {string} featureIndexProp The property name for the feature index in the shader.
100
+ * @param {string} pointIndexProp The property name for the point index in the shader.
101
+ * @returns {string} A GLSL shader string.
102
+ */
103
+ export function getRandomPerPointShader(opacity: number, featureIndexProp: string, pointIndexProp: string): string;
104
+ /**
105
+ * Generate a shader for random-per-point encoding with feature selection.
106
+ * Selected points get a pseudo-random color; unselected get the default color.
107
+ * @param {number[]} featureIndices Numeric indices of selected features.
108
+ * @param {[number, number, number]} defaultColor RGB (0-255) for unselected.
109
+ * @param {number} opacity Opacity (0-1).
110
+ * @param {string} featureIndexProp The property name for the feature index in the shader.
111
+ * @param {string} pointIndexProp The property name for the point index in the shader.
112
+ * @returns {string} A GLSL shader string.
113
+ */
114
+ export function getRandomPerPointWithSelectionShader(featureIndices: number[], defaultColor: [number, number, number], opacity: number, featureIndexProp: string, pointIndexProp: string): string;
115
+ /**
116
+ * Generate a shader for random-per-point encoding with feature selection
117
+ * and featureFilterMode='featureSelection' (hide unselected points).
118
+ * @param {number[]} featureIndices Numeric indices of selected features.
119
+ * @param {number} opacity Opacity (0-1).
120
+ * @param {string} featureIndexProp The property name for the feature index in the shader.
121
+ * @param {string} pointIndexProp The property name for the point index in the shader.
122
+ * @returns {string} A GLSL shader string.
123
+ */
124
+ export function getRandomPerPointFilteredShader(featureIndices: number[], opacity: number, featureIndexProp: string, pointIndexProp: string): string;
125
+ export function getPointsShader(layerCoordination: any): string;
126
+ //# sourceMappingURL=shader-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shader-utils.d.ts","sourceRoot":"","sources":["../src/shader-utils.js"],"names":[],"mappings":"AAwCA;;;;;;GAMG;AACH,wDAJW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,WACxB,MAAM,GACJ,MAAM,CAUlB;AAGD;;;;;;;;;GASG;AACH,qEAPW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,WACxB,MAAM,kBACN,MAAM,EAAE,gBACR,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,oBACxB,MAAM,GACJ,MAAM,CA4BlB;AAGD;;;;;;;;GAQG;AACH,gEANW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,WACxB,MAAM,kBACN,MAAM,EAAE,oBACR,MAAM,GACJ,MAAM,CA0BlB;AAMD;;;;;;;GAOG;AACH,+DAJW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,WACxB,MAAM,GACJ,MAAM,CAUlB;AAED;;;;;;;;;;;;;;GAcG;AACH,oEAXW,MAAM,EAAE,iBACR,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,eAE1B,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,gBAExB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,WAExB,MAAM,oBACN,MAAM,GACJ,MAAM,CA+BlB;AAED;;;;;;;;;;GAUG;AACH,+DARW,MAAM,EAAE,iBACR,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,eAE1B,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,WACxB,MAAM,oBACN,MAAM,GACJ,MAAM,CAoClB;AAMD;;;;;;GAMG;AACH,kDAJW,MAAM,oBACN,MAAM,GACJ,MAAM,CAkBlB;AAED;;;;;;;;;GASG;AACH,sEANW,MAAM,EAAE,gBACR,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,WACxB,MAAM,oBACN,MAAM,GACJ,MAAM,CAkClB;AAED;;;;;;;GAOG;AACH,iEALW,MAAM,EAAE,WACR,MAAM,oBACN,MAAM,GACJ,MAAM,CA8BlB;AAuBD;;;;;;;GAOG;AACH,iDALW,MAAM,oBACN,MAAM,kBACN,MAAM,GACJ,MAAM,CAelB;AAED;;;;;;;;;GASG;AACH,qEAPW,MAAM,EAAE,gBACR,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,WACxB,MAAM,oBACN,MAAM,kBACN,MAAM,GACJ,MAAM,CAgClB;AAED;;;;;;;;GAQG;AACH,gEANW,MAAM,EAAE,WACR,MAAM,oBACN,MAAM,kBACN,MAAM,GACJ,MAAM,CA8BlB;AAGD,gEAwKC"}
@@ -0,0 +1,547 @@
1
+ // Utilities for constructing shaders that
2
+ // handle the coloring of Neuroglancer point annotation layers.
3
+ // References:
4
+ // - https://github.com/vitessce/vitessce/issues/2359#issuecomment-3572906947
5
+ // - https://chanzuckerberg.github.io/cryoet-data-portal/stable/neuroglancer_quickstart.html
6
+ import { PALETTE, getDefaultColor } from '@vitessce/utils';
7
+ /**
8
+ * Normalize an RGB color array from [0, 255] to [0, 1].
9
+ * @param {[number, number, number]} rgbColor
10
+ * @returns {[number, number, number]}
11
+ */
12
+ function normalizeColor(rgbColor) {
13
+ return rgbColor.map(c => c / 255);
14
+ }
15
+ /**
16
+ * Format a normalized color as a GLSL vec3 literal.
17
+ * @param {[number, number, number]} normalizedColor
18
+ * @returns {string}
19
+ */
20
+ function toVec3(normalizedColor) {
21
+ return `vec3(${normalizedColor.join(', ')})`;
22
+ }
23
+ /**
24
+ * Format a normalized color as a GLSL vec4 literal.
25
+ * @param {[number, number, number]} normalizedColor
26
+ * @param {number} alpha
27
+ * @returns {string}
28
+ */
29
+ function toVec4(normalizedColor, alpha) {
30
+ return `vec4(${normalizedColor.join(', ')}, ${alpha})`;
31
+ }
32
+ // ============================================================
33
+ // Case 1: spatialLayerColor
34
+ // ============================================================
35
+ /**
36
+ * Generate a shader for spatialLayerColor encoding with no feature selection.
37
+ * All points get the static color.
38
+ * @param {[number, number, number]} staticColor RGB (0-255).
39
+ * @param {number} opacity Opacity (0-1).
40
+ * @returns {string} A GLSL shader string.
41
+ */
42
+ export function getSpatialLayerColorShader(staticColor, opacity) {
43
+ const norm = normalizeColor(staticColor);
44
+ // lang: glsl
45
+ return `
46
+ void main() {
47
+ setColor(${toVec4(norm, opacity)});
48
+ }
49
+ `;
50
+ }
51
+ /**
52
+ * Generate a shader for spatialLayerColor encoding with feature selection.
53
+ * Selected features get the static color; unselected get the default color.
54
+ * @param {[number, number, number]} staticColor RGB (0-255).
55
+ * @param {number} opacity Opacity (0-1).
56
+ * @param {number[]} featureIndices Numeric indices of selected features.
57
+ * @param {[number, number, number]} defaultColor RGB (0-255) for unselected points.
58
+ * @param {string} featureIndexProp The property name for the feature index in the shader.
59
+ * @returns {string} A GLSL shader string.
60
+ */
61
+ export function getSpatialLayerColorWithSelectionShader(staticColor, opacity, featureIndices, defaultColor, featureIndexProp) {
62
+ const normStatic = normalizeColor(staticColor);
63
+ const normDefault = normalizeColor(defaultColor);
64
+ const numFeatures = featureIndices.length;
65
+ const indicesArr = `int selectedIndices[${numFeatures}] = int[${numFeatures}](${featureIndices.join(', ')});`;
66
+ // lang: glsl
67
+ return `
68
+ void main() {
69
+ int geneIndex = prop_${featureIndexProp}();
70
+ ${indicesArr}
71
+ bool isSelected = false;
72
+ for (int i = 0; i < ${numFeatures}; ++i) {
73
+ if (geneIndex == selectedIndices[i]) {
74
+ isSelected = true;
75
+ }
76
+ }
77
+ if (isSelected) {
78
+ setColor(${toVec4(normStatic, opacity)});
79
+ } else {
80
+ setColor(${toVec4(normDefault, opacity)});
81
+ }
82
+ }
83
+ `;
84
+ }
85
+ /**
86
+ * Generate a shader for spatialLayerColor encoding with feature selection
87
+ * and featureFilterMode='featureSelection' (hide unselected points).
88
+ * @param {[number, number, number]} staticColor RGB (0-255).
89
+ * @param {number} opacity Opacity (0-1).
90
+ * @param {number[]} featureIndices Numeric indices of selected features.
91
+ * @param {string} featureIndexProp The property name for the feature index in the shader.
92
+ * @returns {string} A GLSL shader string.
93
+ */
94
+ export function getSpatialLayerColorFilteredShader(staticColor, opacity, featureIndices, featureIndexProp) {
95
+ const normStatic = normalizeColor(staticColor);
96
+ const numFeatures = featureIndices.length;
97
+ const indicesArr = `int selectedIndices[${numFeatures}] = int[${numFeatures}](${featureIndices.join(', ')});`;
98
+ // lang: glsl
99
+ return `
100
+ void main() {
101
+ int geneIndex = prop_${featureIndexProp}();
102
+ ${indicesArr}
103
+ bool isSelected = false;
104
+ for (int i = 0; i < ${numFeatures}; ++i) {
105
+ if (geneIndex == selectedIndices[i]) {
106
+ isSelected = true;
107
+ }
108
+ }
109
+ if (!isSelected) {
110
+ discard;
111
+ }
112
+ setColor(${toVec4(normStatic, opacity)});
113
+ }
114
+ `;
115
+ }
116
+ // ============================================================
117
+ // Case 2: geneSelection
118
+ // ============================================================
119
+ /**
120
+ * Generate a shader for geneSelection encoding with no feature selection.
121
+ * All points get the static color (since no features are selected to
122
+ * determine per-feature colors).
123
+ * @param {[number, number, number]} staticColor RGB (0-255).
124
+ * @param {number} opacity Opacity (0-1).
125
+ * @returns {string} A GLSL shader string.
126
+ */
127
+ export function getGeneSelectionNoSelectionShader(staticColor, opacity) {
128
+ const norm = normalizeColor(staticColor);
129
+ // lang: glsl
130
+ return `
131
+ void main() {
132
+ setColor(${toVec4(norm, opacity)});
133
+ }
134
+ `;
135
+ }
136
+ /**
137
+ * Generate a shader for geneSelection encoding with feature selection.
138
+ * Each selected feature gets its color from featureColor; unselected
139
+ * points get the default color.
140
+ * @param {number[]} featureIndices Numeric indices of selected features.
141
+ * @param {[number, number, number][]} featureColors RGB (0-255) for each
142
+ * selected feature, in the same order as featureIndices.
143
+ * @param {[number, number, number]} staticColor Fallback RGB (0-255)
144
+ * for selected features without a specified color.
145
+ * @param {[number, number, number]} defaultColor RGB (0-255) for
146
+ * unselected points.
147
+ * @param {number} opacity Opacity (0-1).
148
+ * @param {string} featureIndexProp The property name for the feature index in the shader.
149
+ * @returns {string} A GLSL shader string.
150
+ */
151
+ export function getGeneSelectionWithSelectionShader(featureIndices, featureColors, staticColor, defaultColor, opacity, featureIndexProp) {
152
+ const numFeatures = featureIndices.length;
153
+ const normDefault = normalizeColor(defaultColor);
154
+ const normColors = featureColors.map(c => normalizeColor(c));
155
+ const normStatic = normalizeColor(staticColor);
156
+ const colorArr = normColors.map(c => (c ? toVec3(c) : toVec3(normStatic)));
157
+ const indicesDecl = `int selectedIndices[${numFeatures}] = int[${numFeatures}](${featureIndices.join(', ')});`;
158
+ const colorsDecl = `vec3 featureColors[${numFeatures}] = vec3[${numFeatures}](${colorArr.join(', ')});`;
159
+ // lang: glsl
160
+ return `
161
+ void main() {
162
+ int geneIndex = prop_${featureIndexProp}();
163
+ ${indicesDecl}
164
+ ${colorsDecl}
165
+ vec4 color = ${toVec4(normDefault, opacity)};
166
+ for (int i = 0; i < ${numFeatures}; ++i) {
167
+ if (geneIndex == selectedIndices[i]) {
168
+ color = vec4(featureColors[i], ${opacity});
169
+ }
170
+ }
171
+ setColor(color);
172
+ }
173
+ `;
174
+ }
175
+ /**
176
+ * Generate a shader for geneSelection encoding with feature selection
177
+ * and featureFilterMode='featureSelection' (hide unselected points).
178
+ * @param {number[]} featureIndices Numeric indices of selected features.
179
+ * @param {[number, number, number][]} featureColors RGB (0-255) for each
180
+ * selected feature.
181
+ * @param {[number, number, number]} staticColor Fallback RGB (0-255).
182
+ * @param {number} opacity Opacity (0-1).
183
+ * @param {string} featureIndexProp The property name for the feature index in the shader.
184
+ * @returns {string} A GLSL shader string.
185
+ */
186
+ export function getGeneSelectionFilteredShader(featureIndices, featureColors, staticColor, opacity, featureIndexProp) {
187
+ const numFeatures = featureIndices.length;
188
+ const normColors = featureColors.map(c => normalizeColor(c));
189
+ const normStatic = normalizeColor(staticColor);
190
+ const colorArr = normColors.map(c => (c ? toVec3(c) : toVec3(normStatic)));
191
+ const indicesDecl = `int selectedIndices[${numFeatures}] = int[${numFeatures}](${featureIndices.join(', ')});`;
192
+ const colorsDecl = `vec3 featureColors[${numFeatures}] = vec3[${numFeatures}](${colorArr.join(', ')});`;
193
+ // lang: glsl
194
+ return `
195
+ void main() {
196
+ int geneIndex = prop_${featureIndexProp}();
197
+ ${indicesDecl}
198
+ ${colorsDecl}
199
+ bool isSelected = false;
200
+ vec3 matchedColor = vec3(0.0);
201
+ for (int i = 0; i < ${numFeatures}; ++i) {
202
+ if (geneIndex == selectedIndices[i]) {
203
+ isSelected = true;
204
+ matchedColor = featureColors[i];
205
+ }
206
+ }
207
+ if (!isSelected) {
208
+ discard;
209
+ }
210
+ setColor(vec4(matchedColor, ${opacity}));
211
+ }
212
+ `;
213
+ }
214
+ // ============================================================
215
+ // Case 3: randomByFeature
216
+ // ============================================================
217
+ /**
218
+ * Generate a shader for randomByFeature encoding with no feature selection.
219
+ * Each feature gets a deterministic color from PALETTE based on its index.
220
+ * @param {number} opacity Opacity (0-1).
221
+ * @param {string} featureIndexProp The property name for the feature index in the shader.
222
+ * @returns {string} A GLSL shader string.
223
+ */
224
+ export function getRandomByFeatureShader(opacity, featureIndexProp) {
225
+ const paletteSize = PALETTE.length;
226
+ const normPalette = PALETTE.map(c => normalizeColor(c));
227
+ const paletteDecl = `vec3 palette[${paletteSize}] = vec3[${paletteSize}](${normPalette.map(c => toVec3(c)).join(', ')});`;
228
+ // lang: glsl
229
+ return `
230
+ void main() {
231
+ int geneIndex = prop_${featureIndexProp}();
232
+ ${paletteDecl}
233
+ int colorIdx = geneIndex - (geneIndex / ${paletteSize}) * ${paletteSize};
234
+ if (colorIdx < 0) { colorIdx = -colorIdx; }
235
+ vec3 color = palette[colorIdx];
236
+ setColor(vec4(color, ${opacity}));
237
+ }
238
+ `;
239
+ }
240
+ /**
241
+ * Generate a shader for randomByFeature encoding with feature selection.
242
+ * Selected features get their deterministic palette color; unselected
243
+ * points get the default color.
244
+ * @param {number[]} featureIndices Numeric indices of selected features.
245
+ * @param {[number, number, number]} defaultColor RGB (0-255) for unselected.
246
+ * @param {number} opacity Opacity (0-1).
247
+ * @param {string} featureIndexProp The property name for the feature index in the shader.
248
+ * @returns {string} A GLSL shader string.
249
+ */
250
+ export function getRandomByFeatureWithSelectionShader(featureIndices, defaultColor, opacity, featureIndexProp) {
251
+ const paletteSize = PALETTE.length;
252
+ const normPalette = PALETTE.map(c => normalizeColor(c));
253
+ const normDefault = normalizeColor(defaultColor);
254
+ const numFeatures = featureIndices.length;
255
+ const paletteDecl = `vec3 palette[${paletteSize}] = vec3[${paletteSize}](${normPalette.map(c => toVec3(c)).join(', ')});`;
256
+ const indicesDecl = `int selectedIndices[${numFeatures}] = int[${numFeatures}](${featureIndices.join(', ')});`;
257
+ // lang: glsl
258
+ return `
259
+ void main() {
260
+ int geneIndex = prop_${featureIndexProp}();
261
+ ${paletteDecl}
262
+ ${indicesDecl}
263
+ bool isSelected = false;
264
+ for (int i = 0; i < ${numFeatures}; ++i) {
265
+ if (geneIndex == selectedIndices[i]) {
266
+ isSelected = true;
267
+ }
268
+ }
269
+ if (isSelected) {
270
+ int colorIdx = geneIndex - (geneIndex / ${paletteSize}) * ${paletteSize};
271
+ if (colorIdx < 0) { colorIdx = -colorIdx; }
272
+ setColor(vec4(palette[colorIdx], ${opacity}));
273
+ } else {
274
+ setColor(${toVec4(normDefault, opacity)});
275
+ }
276
+ }
277
+ `;
278
+ }
279
+ /**
280
+ * Generate a shader for randomByFeature encoding with feature selection
281
+ * and featureFilterMode='featureSelection' (hide unselected points).
282
+ * @param {number[]} featureIndices Numeric indices of selected features.
283
+ * @param {number} opacity Opacity (0-1).
284
+ * @param {string} featureIndexProp The property name for the feature index in the shader.
285
+ * @returns {string} A GLSL shader string.
286
+ */
287
+ export function getRandomByFeatureFilteredShader(featureIndices, opacity, featureIndexProp) {
288
+ const paletteSize = PALETTE.length;
289
+ const normPalette = PALETTE.map(c => normalizeColor(c));
290
+ const numFeatures = featureIndices.length;
291
+ const paletteDecl = `vec3 palette[${paletteSize}] = vec3[${paletteSize}](${normPalette.map(c => toVec3(c)).join(', ')});`;
292
+ const indicesDecl = `int selectedIndices[${numFeatures}] = int[${numFeatures}](${featureIndices.join(', ')});`;
293
+ // lang: glsl
294
+ return `
295
+ void main() {
296
+ int geneIndex = prop_${featureIndexProp}();
297
+ ${paletteDecl}
298
+ ${indicesDecl}
299
+ bool isSelected = false;
300
+ for (int i = 0; i < ${numFeatures}; ++i) {
301
+ if (geneIndex == selectedIndices[i]) {
302
+ isSelected = true;
303
+ }
304
+ }
305
+ if (!isSelected) {
306
+ discard;
307
+ }
308
+ int colorIdx = geneIndex - (geneIndex / ${paletteSize}) * ${paletteSize};
309
+ if (colorIdx < 0) { colorIdx = -colorIdx; }
310
+ setColor(vec4(palette[colorIdx], ${opacity}));
311
+ }
312
+ `;
313
+ }
314
+ // ============================================================
315
+ // Case 4: random (per point)
316
+ // ============================================================
317
+ /**
318
+ * GLSL helper function that produces a pseudo-random float in [0, 1]
319
+ * from an integer value and a seed. Shared across random-per-point shaders.
320
+ * @returns {string} GLSL function source.
321
+ */
322
+ function hashToFloatGlsl() {
323
+ return `
324
+ float hashToFloat(int v, int seed) {
325
+ int h = v ^ (seed * 16777619);
326
+ h = h * 747796405 + 2891336453;
327
+ h = ((h >> 16) ^ h) * 2654435769;
328
+ h = ((h >> 16) ^ h);
329
+ return float(h & 0x7FFFFFFF) / float(0x7FFFFFFF);
330
+ }
331
+ `;
332
+ }
333
+ /**
334
+ * Generate a shader for random-per-point encoding with no feature selection.
335
+ * Each point gets a pseudo-random color based on its index.
336
+ * @param {number} opacity Opacity (0-1).
337
+ * @param {string} featureIndexProp The property name for the feature index in the shader.
338
+ * @param {string} pointIndexProp The property name for the point index in the shader.
339
+ * @returns {string} A GLSL shader string.
340
+ */
341
+ export function getRandomPerPointShader(opacity, featureIndexProp, pointIndexProp) {
342
+ // lang: glsl
343
+ return `
344
+ ${hashToFloatGlsl()}
345
+ void main() {
346
+ int geneIndex = prop_${featureIndexProp}();
347
+ int pointIndex = prop_${pointIndexProp}();
348
+ float r = hashToFloat(pointIndex, 0);
349
+ float g = hashToFloat(pointIndex, 1);
350
+ float b = hashToFloat(pointIndex, 2);
351
+ setColor(vec4(r, g, b, ${opacity}));
352
+ }
353
+ `;
354
+ }
355
+ /**
356
+ * Generate a shader for random-per-point encoding with feature selection.
357
+ * Selected points get a pseudo-random color; unselected get the default color.
358
+ * @param {number[]} featureIndices Numeric indices of selected features.
359
+ * @param {[number, number, number]} defaultColor RGB (0-255) for unselected.
360
+ * @param {number} opacity Opacity (0-1).
361
+ * @param {string} featureIndexProp The property name for the feature index in the shader.
362
+ * @param {string} pointIndexProp The property name for the point index in the shader.
363
+ * @returns {string} A GLSL shader string.
364
+ */
365
+ export function getRandomPerPointWithSelectionShader(featureIndices, defaultColor, opacity, featureIndexProp, pointIndexProp) {
366
+ const normDefault = normalizeColor(defaultColor);
367
+ const numFeatures = featureIndices.length;
368
+ const indicesDecl = `int selectedIndices[${numFeatures}] = int[${numFeatures}](${featureIndices.join(', ')});`;
369
+ // lang: glsl
370
+ return `
371
+ ${hashToFloatGlsl()}
372
+ void main() {
373
+ int geneIndex = prop_${featureIndexProp}();
374
+ int pointIndex = prop_${pointIndexProp}();
375
+ ${indicesDecl}
376
+ bool isSelected = false;
377
+ for (int i = 0; i < ${numFeatures}; ++i) {
378
+ if (geneIndex == selectedIndices[i]) {
379
+ isSelected = true;
380
+ }
381
+ }
382
+ if (isSelected) {
383
+ float r = hashToFloat(pointIndex, 0);
384
+ float g = hashToFloat(pointIndex, 1);
385
+ float b = hashToFloat(pointIndex, 2);
386
+ setColor(vec4(r, g, b, ${opacity}));
387
+ } else {
388
+ setColor(${toVec4(normDefault, opacity)});
389
+ }
390
+ }
391
+ `;
392
+ }
393
+ /**
394
+ * Generate a shader for random-per-point encoding with feature selection
395
+ * and featureFilterMode='featureSelection' (hide unselected points).
396
+ * @param {number[]} featureIndices Numeric indices of selected features.
397
+ * @param {number} opacity Opacity (0-1).
398
+ * @param {string} featureIndexProp The property name for the feature index in the shader.
399
+ * @param {string} pointIndexProp The property name for the point index in the shader.
400
+ * @returns {string} A GLSL shader string.
401
+ */
402
+ export function getRandomPerPointFilteredShader(featureIndices, opacity, featureIndexProp, pointIndexProp) {
403
+ const numFeatures = featureIndices.length;
404
+ const indicesDecl = `int selectedIndices[${numFeatures}] = int[${numFeatures}](${featureIndices.join(', ')});`;
405
+ // lang: glsl
406
+ return `
407
+ ${hashToFloatGlsl()}
408
+ void main() {
409
+ int geneIndex = prop_${featureIndexProp}();
410
+ int pointIndex = prop_${pointIndexProp}();
411
+ ${indicesDecl}
412
+ bool isSelected = false;
413
+ for (int i = 0; i < ${numFeatures}; ++i) {
414
+ if (geneIndex == selectedIndices[i]) {
415
+ isSelected = true;
416
+ }
417
+ }
418
+ if (!isSelected) {
419
+ discard;
420
+ }
421
+ float r = hashToFloat(pointIndex, 0);
422
+ float g = hashToFloat(pointIndex, 1);
423
+ float b = hashToFloat(pointIndex, 2);
424
+ setColor(vec4(r, g, b, ${opacity}));
425
+ }
426
+ `;
427
+ }
428
+ export function getPointsShader(layerCoordination) {
429
+ const { theme, featureIndex, spatialLayerOpacity, obsColorEncoding, spatialLayerColor, featureSelection, featureFilterMode, featureColor, featureIndexProp, pointIndexProp, } = layerCoordination;
430
+ const defaultColor = getDefaultColor(theme);
431
+ const opacity = spatialLayerOpacity ?? 1.0;
432
+ const staticColor = (Array.isArray(spatialLayerColor) && spatialLayerColor.length === 3
433
+ ? spatialLayerColor
434
+ : defaultColor);
435
+ const hasFeatureSelection = (Array.isArray(featureSelection) && featureSelection.length > 0);
436
+ const isFiltered = featureFilterMode === 'featureSelection';
437
+ // Resolve selected feature names to numeric indices.
438
+ let featureIndices = [];
439
+ if (hasFeatureSelection && Array.isArray(featureIndex)) {
440
+ featureIndices = featureSelection
441
+ .map(name => featureIndex.indexOf(name))
442
+ .filter(i => i >= 0);
443
+ }
444
+ const hasResolvedIndices = featureIndices.length > 0;
445
+ // Resolve per-feature colors (in the same order as featureIndices).
446
+ const resolvedFeatureColors = hasResolvedIndices
447
+ ? featureSelection
448
+ .filter(name => featureIndex?.indexOf(name) >= 0)
449
+ .map((name) => {
450
+ const match = Array.isArray(featureColor)
451
+ ? featureColor.find(fc => fc.name === name)?.color
452
+ : null;
453
+ return match || staticColor;
454
+ })
455
+ : [];
456
+ // Points coloring cases:
457
+ // (See `createPointLayer` in spatial-beta/Spatial.js for more background.)
458
+ // Coloring cases:
459
+ // - spatialLayerColor: one color for all points.
460
+ // consider all as selected when featureSelection is null.
461
+ // - spatialLayerColor with featureSelection: one color for
462
+ // all selected points, default color for unselected points
463
+ // - spatialLayerColor with featureSelection and
464
+ // featureFilterMode 'featureSelection': one color for selected points,
465
+ // do not show unselected points
466
+ // - geneSelection: use colors from "featureColor".
467
+ // consider all as selected when featureSelection is null.
468
+ // - geneSelection with featureSelection: use colors from
469
+ // "featureColor" (array of { name, color: [r, g, b] }) for
470
+ // selected features, default color for unselected points
471
+ // - geneSelection with featureFilterMode 'featureSelection': use colors
472
+ // from "featureColor" for selected features,
473
+ // do not show unselected points
474
+ // - randomByFeature: random color for each feature
475
+ // (deterministic based on feature index).
476
+ // consider all as selected when featureSelection is null.
477
+ // - randomByFeature with preferFeatureColor: use colors from
478
+ // "featureColor" (array of { name, color: [r, g, b] }) where
479
+ // available, and random colors otherwise.
480
+ // - randomByFeature with featureSelection: random color for
481
+ // selected features, default color for unselected points
482
+ // - randomByFeature with featureSelection and
483
+ // featureFilterMode 'featureSelection': random color for
484
+ // selected features, do not show unselected points
485
+ // - random: random color for each point
486
+ // (deterministic based on point index).
487
+ // consider all as selected when featureSelection is null.
488
+ // - random with preferFeatureColor: use colors from "featureColor"
489
+ // (array of { name, color: [r, g, b] }) where available,
490
+ // and random colors otherwise.
491
+ // - random with featureSelection: random color for selected points,
492
+ // default color for unselected points
493
+ // - random with featureSelection and
494
+ // featureFilterMode 'featureSelection': random color for selected
495
+ // points, do not show unselected points
496
+ // ---- spatialLayerColor ----
497
+ if (obsColorEncoding === 'spatialLayerColor') {
498
+ if (!hasFeatureSelection || !hasResolvedIndices) {
499
+ return getSpatialLayerColorShader(staticColor, opacity);
500
+ }
501
+ if (isFiltered) {
502
+ return getSpatialLayerColorFilteredShader(staticColor, opacity, featureIndices, featureIndexProp);
503
+ }
504
+ return getSpatialLayerColorWithSelectionShader(staticColor, opacity, featureIndices, defaultColor, featureIndexProp);
505
+ }
506
+ // ---- geneSelection ----
507
+ if (obsColorEncoding === 'geneSelection') {
508
+ if (!featureIndexProp) {
509
+ 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.');
510
+ }
511
+ if (!hasFeatureSelection || !hasResolvedIndices) {
512
+ return getGeneSelectionNoSelectionShader(staticColor, opacity);
513
+ }
514
+ if (isFiltered) {
515
+ return getGeneSelectionFilteredShader(featureIndices, resolvedFeatureColors, staticColor, opacity, featureIndexProp);
516
+ }
517
+ return getGeneSelectionWithSelectionShader(featureIndices, resolvedFeatureColors, staticColor, defaultColor, opacity, featureIndexProp);
518
+ }
519
+ // ---- randomByFeature ----
520
+ if (obsColorEncoding === 'randomByFeature') {
521
+ if (!featureIndexProp) {
522
+ 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.');
523
+ }
524
+ if (!hasFeatureSelection || !hasResolvedIndices) {
525
+ return getRandomByFeatureShader(opacity, featureIndexProp);
526
+ }
527
+ if (isFiltered) {
528
+ return getRandomByFeatureFilteredShader(featureIndices, opacity, featureIndexProp);
529
+ }
530
+ return getRandomByFeatureWithSelectionShader(featureIndices, defaultColor, opacity, featureIndexProp);
531
+ }
532
+ // ---- random (per point) ----
533
+ if (obsColorEncoding === 'random') {
534
+ if (!pointIndexProp) {
535
+ throw new Error('In order to use per-point color encoding for Neuroglancer Points, options.pointIndexProp must be specified for the obsPoints.ng-annotations fileType in the Vitessce configuration.');
536
+ }
537
+ if (!hasFeatureSelection || !hasResolvedIndices) {
538
+ return getRandomPerPointShader(opacity, featureIndexProp, pointIndexProp);
539
+ }
540
+ if (isFiltered) {
541
+ return getRandomPerPointFilteredShader(featureIndices, opacity, featureIndexProp, pointIndexProp);
542
+ }
543
+ return getRandomPerPointWithSelectionShader(featureIndices, defaultColor, opacity, featureIndexProp, pointIndexProp);
544
+ }
545
+ // Fallback: static color.
546
+ return getSpatialLayerColorShader(staticColor, opacity);
547
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=shader-utils.test.d.ts.map