@vitessce/gl 2.0.3-beta.0 → 3.0.0

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.
Files changed (109) hide show
  1. package/dist/deflate-36830437.js +11 -0
  2. package/dist/index-d34ff949.js +120610 -0
  3. package/dist/index.js +33 -16
  4. package/dist/jpeg-a66190dc.js +838 -0
  5. package/dist/lerc-21af7ec8.js +2004 -0
  6. package/dist/lzw-76194936.js +126 -0
  7. package/dist/packbits-bf7850c4.js +28 -0
  8. package/dist/pako.esm-68f84e2a.js +4022 -0
  9. package/dist/raw-05d82ade.js +10 -0
  10. package/dist/webimage-1ceac06a.js +30 -0
  11. package/dist-tsc/BitmaskLayer.d.ts +74 -0
  12. package/dist-tsc/BitmaskLayer.d.ts.map +1 -0
  13. package/{dist → dist-tsc}/BitmaskLayer.js +14 -4
  14. package/dist-tsc/HeatmapBitmapLayer.d.ts +93 -0
  15. package/dist-tsc/HeatmapBitmapLayer.d.ts.map +1 -0
  16. package/{dist → dist-tsc}/HeatmapBitmapLayer.js +3 -3
  17. package/dist-tsc/HeatmapCompositeTextLayer.d.ts +11 -0
  18. package/dist-tsc/HeatmapCompositeTextLayer.d.ts.map +1 -0
  19. package/{dist → dist-tsc}/HeatmapCompositeTextLayer.js +1 -1
  20. package/dist-tsc/PaddedExpressionHeatmapBitmapLayer.d.ts +93 -0
  21. package/dist-tsc/PaddedExpressionHeatmapBitmapLayer.d.ts.map +1 -0
  22. package/{dist → dist-tsc}/PaddedExpressionHeatmapBitmapLayer.js +3 -3
  23. package/dist-tsc/PixelatedBitmapLayer.d.ts +10 -0
  24. package/dist-tsc/PixelatedBitmapLayer.d.ts.map +1 -0
  25. package/{dist → dist-tsc}/PixelatedBitmapLayer.js +1 -1
  26. package/dist-tsc/ScaledExpressionExtension/ScaledExpressionExtension.d.ts +62 -0
  27. package/dist-tsc/ScaledExpressionExtension/ScaledExpressionExtension.d.ts.map +1 -0
  28. package/{dist → dist-tsc}/ScaledExpressionExtension/ScaledExpressionExtension.js +2 -2
  29. package/dist-tsc/ScaledExpressionExtension/index.d.ts +3 -0
  30. package/dist-tsc/ScaledExpressionExtension/index.d.ts.map +1 -0
  31. package/{dist → dist-tsc}/ScaledExpressionExtension/index.js +1 -1
  32. package/dist-tsc/ScaledExpressionExtension/shader-module.d.ts +17 -0
  33. package/dist-tsc/ScaledExpressionExtension/shader-module.d.ts.map +1 -0
  34. package/{dist → dist-tsc}/ScaledExpressionExtension/shader-module.js +1 -1
  35. package/dist-tsc/SelectionExtension/SelectionExtension.d.ts +18 -0
  36. package/dist-tsc/SelectionExtension/SelectionExtension.d.ts.map +1 -0
  37. package/{dist → dist-tsc}/SelectionExtension/SelectionExtension.js +1 -1
  38. package/dist-tsc/SelectionExtension/index.d.ts +3 -0
  39. package/dist-tsc/SelectionExtension/index.d.ts.map +1 -0
  40. package/dist-tsc/SelectionExtension/index.js +2 -0
  41. package/dist-tsc/SelectionExtension/shader-module.d.ts +12 -0
  42. package/dist-tsc/SelectionExtension/shader-module.d.ts.map +1 -0
  43. package/dist-tsc/SelectionLayer.d.ts +15 -0
  44. package/dist-tsc/SelectionLayer.d.ts.map +1 -0
  45. package/{dist → dist-tsc}/SelectionLayer.js +1 -11
  46. package/dist-tsc/bitmask-layer-shaders.d.ts +3 -0
  47. package/dist-tsc/bitmask-layer-shaders.d.ts.map +1 -0
  48. package/{dist → dist-tsc}/bitmask-layer-shaders.js +1 -1
  49. package/dist-tsc/constants.d.ts +8 -0
  50. package/dist-tsc/constants.d.ts.map +1 -0
  51. package/dist-tsc/deck.d.ts +2 -0
  52. package/dist-tsc/deck.d.ts.map +1 -0
  53. package/dist-tsc/glsl/index.d.ts +2 -0
  54. package/dist-tsc/glsl/index.d.ts.map +1 -0
  55. package/dist-tsc/heatmap-bitmap-layer-shaders.d.ts +13 -0
  56. package/dist-tsc/heatmap-bitmap-layer-shaders.d.ts.map +1 -0
  57. package/{dist → dist-tsc}/heatmap-bitmap-layer-shaders.js +1 -1
  58. package/dist-tsc/heatmap-constants.d.ts +20 -0
  59. package/dist-tsc/heatmap-constants.d.ts.map +1 -0
  60. package/dist-tsc/index.d.ts +14 -0
  61. package/dist-tsc/index.d.ts.map +1 -0
  62. package/dist-tsc/index.js +19 -0
  63. package/dist-tsc/luma.d.ts +2 -0
  64. package/dist-tsc/luma.d.ts.map +1 -0
  65. package/dist-tsc/padded-expression-heatmap-bitmap-layer-shaders.d.ts +13 -0
  66. package/dist-tsc/padded-expression-heatmap-bitmap-layer-shaders.d.ts.map +1 -0
  67. package/{dist → dist-tsc}/padded-expression-heatmap-bitmap-layer-shaders.js +1 -1
  68. package/dist-tsc/selection-utils.d.ts +19 -0
  69. package/dist-tsc/selection-utils.d.ts.map +1 -0
  70. package/{dist → dist-tsc}/selection-utils.js +1 -1
  71. package/dist-tsc/viv.d.ts +2 -0
  72. package/dist-tsc/viv.d.ts.map +1 -0
  73. package/package.json +16 -7
  74. package/src/BitmaskLayer.js +175 -0
  75. package/src/HeatmapBitmapLayer.js +144 -0
  76. package/src/HeatmapCompositeTextLayer.js +156 -0
  77. package/src/PaddedExpressionHeatmapBitmapLayer.js +154 -0
  78. package/src/PixelatedBitmapLayer.js +30 -0
  79. package/src/ScaledExpressionExtension/ScaledExpressionExtension.js +117 -0
  80. package/src/ScaledExpressionExtension/index.js +3 -0
  81. package/src/ScaledExpressionExtension/shader-module.js +35 -0
  82. package/src/SelectionExtension/SelectionExtension.js +34 -0
  83. package/src/SelectionExtension/index.js +3 -0
  84. package/src/SelectionExtension/shader-module.js +22 -0
  85. package/src/SelectionLayer.js +187 -0
  86. package/src/bitmask-layer-shaders.js +92 -0
  87. package/src/constants.js +13 -0
  88. package/src/deck.js +4 -0
  89. package/src/glsl/README.md +8 -0
  90. package/src/glsl/colormaps.in.glsl +15 -0
  91. package/src/glsl/index.js +341 -0
  92. package/src/heatmap-bitmap-layer-shaders.js +111 -0
  93. package/src/heatmap-constants.js +30 -0
  94. package/src/index.js +36 -0
  95. package/src/luma.js +2 -0
  96. package/src/padded-expression-heatmap-bitmap-layer-shaders.js +145 -0
  97. package/src/selection-utils.js +109 -0
  98. package/src/viv.js +20 -0
  99. package/dist/SelectionExtension/index.js +0 -2
  100. package/dist/layer-controller.js +0 -109
  101. package/dist/spatial.js +0 -281
  102. package/dist/spatial.test.js +0 -8
  103. /package/{dist → dist-tsc}/SelectionExtension/shader-module.js +0 -0
  104. /package/{dist → dist-tsc}/constants.js +0 -0
  105. /package/{dist → dist-tsc}/deck.js +0 -0
  106. /package/{dist → dist-tsc}/glsl/index.js +0 -0
  107. /package/{dist → dist-tsc}/heatmap-constants.js +0 -0
  108. /package/{dist → dist-tsc}/luma.js +0 -0
  109. /package/{dist → dist-tsc}/viv.js +0 -0
@@ -0,0 +1,111 @@
1
+ import { colormaps } from './glsl/index.js';
2
+
3
+ /**
4
+ * No change to the vertex shader from the base BitmapLayer.
5
+ * Reference: https://github.com/visgl/deck.gl/blob/8.2-release/modules/layers/src/bitmap-layer/bitmap-layer-vertex.js
6
+ */
7
+ export const vertexShader = `
8
+ #define SHADER_NAME heatmap-bitmap-layer-vertex-shader
9
+
10
+ attribute vec2 texCoords;
11
+ attribute vec3 positions;
12
+ attribute vec3 positions64Low;
13
+
14
+ varying vec2 vTexCoord;
15
+
16
+ const vec3 pickingColor = vec3(1.0, 0.0, 0.0);
17
+
18
+ void main(void) {
19
+ geometry.worldPosition = positions;
20
+ geometry.uv = texCoords;
21
+ geometry.pickingColor = pickingColor;
22
+
23
+ gl_Position = project_position_to_clipspace(positions, positions64Low, vec3(0.0), geometry.position);
24
+ DECKGL_FILTER_GL_POSITION(gl_Position, geometry);
25
+
26
+ vTexCoord = texCoords;
27
+
28
+ vec4 color = vec4(0.0);
29
+ DECKGL_FILTER_COLOR(color, geometry);
30
+ }
31
+ `;
32
+
33
+ /**
34
+ * Fragment shader adapted to perform aggregation and
35
+ * take color scale functions + sliders into account.
36
+ * Reference: https://github.com/visgl/deck.gl/blob/8.2-release/modules/layers/src/bitmap-layer/bitmap-layer-fragment.js
37
+ * Reference: https://github.com/hms-dbmi/viv/blob/06231ae02cac1ff57ba458c71e9bc59ed2fc4f8b/src/layers/XRLayer/xr-layer-fragment-colormap.webgl1.glsl
38
+ */
39
+ export const fragmentShader = `
40
+ #define SHADER_NAME heatmap-bitmap-layer-fragment-shader
41
+
42
+ #ifdef GL_ES
43
+ precision mediump float;
44
+ #endif
45
+
46
+ ${colormaps}
47
+
48
+ // The texture (GL.LUMINANCE & Uint8Array).
49
+ uniform sampler2D uBitmapTexture;
50
+
51
+ // What are the dimensions of the texture (width, height)?
52
+ uniform vec2 uTextureSize;
53
+
54
+ // How many consecutive pixels should be aggregated together along each axis?
55
+ uniform vec2 uAggSize;
56
+
57
+ // What are the values of the color scale sliders?
58
+ uniform vec2 uColorScaleRange;
59
+
60
+ // The texture coordinate, varying (interpolated between values set by the vertex shader).
61
+ varying vec2 vTexCoord;
62
+
63
+ void main(void) {
64
+ // Compute 1 pixel in texture coordinates
65
+ vec2 onePixel = vec2(1.0, 1.0) / uTextureSize;
66
+
67
+ vec2 viewCoord = vec2(floor(vTexCoord.x * uTextureSize.x), floor(vTexCoord.y * uTextureSize.y));
68
+
69
+ // Compute (x % aggSizeX, y % aggSizeY).
70
+ // These values will be the number of values to the left / above the current position to consider.
71
+ vec2 modAggSize = vec2(-1.0 * mod(viewCoord.x, uAggSize.x), -1.0 * mod(viewCoord.y, uAggSize.y));
72
+
73
+ // Take the sum of values along each axis.
74
+ float intensitySum = 0.0;
75
+ vec2 offsetPixels = vec2(0.0, 0.0);
76
+
77
+ for(int i = 0; i < 16; i++) {
78
+ // Check to break outer loop early.
79
+ // Uniforms cannot be used as conditions in GLSL for loops.
80
+ if(float(i) >= uAggSize.y) {
81
+ // Done in the y direction.
82
+ break;
83
+ }
84
+
85
+ offsetPixels = vec2(offsetPixels.x, (modAggSize.y + float(i)) * onePixel.y);
86
+
87
+ for(int j = 0; j < 16; j++) {
88
+ // Check to break inner loop early.
89
+ // Uniforms cannot be used as conditions in GLSL for loops.
90
+ if(float(j) >= uAggSize.x) {
91
+ // Done in the x direction.
92
+ break;
93
+ }
94
+
95
+ offsetPixels = vec2((modAggSize.x + float(j)) * onePixel.x, offsetPixels.y);
96
+ intensitySum += texture2D(uBitmapTexture, vTexCoord + offsetPixels).r;
97
+ }
98
+ }
99
+
100
+ // Compute the mean value.
101
+ float intensityMean = intensitySum / (uAggSize.x * uAggSize.y);
102
+
103
+ // Re-scale using the color scale slider values.
104
+ float scaledIntensityMean = (intensityMean - uColorScaleRange[0]) / max(0.005, (uColorScaleRange[1] - uColorScaleRange[0]));
105
+
106
+ gl_FragColor = COLORMAP_FUNC(clamp(scaledIntensityMean, 0.0, 1.0));
107
+
108
+ geometry.uv = vTexCoord;
109
+ DECKGL_FILTER_COLOR(gl_FragColor, geometry);
110
+ }
111
+ `;
@@ -0,0 +1,30 @@
1
+ import GL from '@luma.gl/constants'; // eslint-disable-line import/no-extraneous-dependencies
2
+
3
+ // Image texture dimensions
4
+ export const TILE_SIZE = 4096;
5
+ // Reshaped data texture dimensions
6
+ export const DATA_TEXTURE_SIZE = 4096;
7
+ export const MIN_ROW_AGG = 1;
8
+ export const MAX_ROW_AGG = 16;
9
+
10
+ export const COLOR_BAR_SIZE = 20;
11
+ export const AXIS_LABEL_TEXT_SIZE = 11;
12
+ export const AXIS_TITLE_TEXT_SIZE = 15;
13
+ export const AXIS_MIN_SIZE = 12;
14
+ export const AXIS_MAX_SIZE = 120;
15
+ export const AXIS_MARGIN = 3;
16
+ export const AXIS_PADDING = 10;
17
+ export const THEME_TO_TEXT_COLOR = {
18
+ dark: [224, 224, 224],
19
+ light: [64, 64, 64],
20
+ };
21
+ export const AXIS_FONT_FAMILY = "-apple-system, 'Helvetica Neue', Arial, sans-serif";
22
+
23
+ export const PIXELATED_TEXTURE_PARAMETERS = {
24
+ // NEAREST for integer data to prevent interpolation.
25
+ [GL.TEXTURE_MIN_FILTER]: GL.NEAREST,
26
+ [GL.TEXTURE_MAG_FILTER]: GL.NEAREST,
27
+ // CLAMP_TO_EDGE to remove tile artifacts.
28
+ [GL.TEXTURE_WRAP_S]: GL.CLAMP_TO_EDGE,
29
+ [GL.TEXTURE_WRAP_T]: GL.CLAMP_TO_EDGE,
30
+ };
package/src/index.js ADDED
@@ -0,0 +1,36 @@
1
+ // Selection Layers
2
+ export { getSelectionLayers } from './selection-utils.js';
3
+
4
+ // Heatmap Layers
5
+ export { default as HeatmapBitmapLayer } from './HeatmapBitmapLayer.js';
6
+ export { default as PixelatedBitmapLayer } from './PixelatedBitmapLayer.js';
7
+ export { default as HeatmapCompositeTextLayer } from './HeatmapCompositeTextLayer.js';
8
+ export { default as PaddedExpressionHeatmapBitmapLayer } from './PaddedExpressionHeatmapBitmapLayer.js';
9
+
10
+ export {
11
+ GLSL_COLORMAPS, GLSL_COLORMAP_DEFAULT, DEFAULT_GL_OPTIONS, SELECTION_TYPE,
12
+ } from './constants.js';
13
+
14
+ // Layer extensions
15
+ export { default as ScaledExpressionExtension } from './ScaledExpressionExtension/index.js';
16
+ export { default as SelectionExtension } from './SelectionExtension/index.js';
17
+ export { default as BitmaskLayer } from './BitmaskLayer.js';
18
+
19
+ export {
20
+ TILE_SIZE, MAX_ROW_AGG, MIN_ROW_AGG,
21
+ COLOR_BAR_SIZE,
22
+ AXIS_MARGIN,
23
+ DATA_TEXTURE_SIZE,
24
+ PIXELATED_TEXTURE_PARAMETERS,
25
+ AXIS_LABEL_TEXT_SIZE,
26
+ AXIS_FONT_FAMILY,
27
+ AXIS_PADDING,
28
+ AXIS_MIN_SIZE,
29
+ AXIS_MAX_SIZE,
30
+ } from './heatmap-constants.js';
31
+ // eslint-disable-next-line react-refresh/only-export-components
32
+ export * as viv from './viv.js';
33
+ // eslint-disable-next-line react-refresh/only-export-components
34
+ export * as luma from './luma.js';
35
+ // eslint-disable-next-line react-refresh/only-export-components
36
+ export * as deck from './deck.js';
package/src/luma.js ADDED
@@ -0,0 +1,2 @@
1
+ export { default as GL } from '@luma.gl/constants';
2
+ export { Texture2D } from '@luma.gl/core';
@@ -0,0 +1,145 @@
1
+ import { colormaps } from './glsl/index.js';
2
+
3
+ /**
4
+ * No change to the vertex shader from the base BitmapLayer.
5
+ * Reference: https://github.com/visgl/deck.gl/blob/8.2-release/modules/layers/src/bitmap-layer/bitmap-layer-vertex.js
6
+ */
7
+ export const vertexShader = `
8
+ #define SHADER_NAME heatmap-bitmap-layer-vertex-shader
9
+
10
+ attribute vec2 texCoords;
11
+ attribute vec3 positions;
12
+ attribute vec3 positions64Low;
13
+
14
+ varying vec2 vTexCoord;
15
+
16
+ const vec3 pickingColor = vec3(1.0, 0.0, 0.0);
17
+
18
+ void main(void) {
19
+ geometry.worldPosition = positions;
20
+ geometry.uv = texCoords;
21
+ geometry.pickingColor = pickingColor;
22
+
23
+ gl_Position = project_position_to_clipspace(positions, positions64Low, vec3(0.0), geometry.position);
24
+ DECKGL_FILTER_GL_POSITION(gl_Position, geometry);
25
+
26
+ vTexCoord = texCoords;
27
+
28
+ vec4 color = vec4(0.0);
29
+ DECKGL_FILTER_COLOR(color, geometry);
30
+ }
31
+ `;
32
+
33
+ /**
34
+ * Fragment shader adapted to perform aggregation and
35
+ * take color scale functions + sliders into account.
36
+ * Reference: https://github.com/visgl/deck.gl/blob/8.2-release/modules/layers/src/bitmap-layer/bitmap-layer-fragment.js
37
+ * Reference: https://github.com/hms-dbmi/viv/blob/06231ae02cac1ff57ba458c71e9bc59ed2fc4f8b/src/layers/XRLayer/xr-layer-fragment-colormap.webgl1.glsl
38
+ */
39
+ export const fragmentShader = `
40
+ #define SHADER_NAME heatmap-bitmap-layer-fragment-shader
41
+
42
+ #ifdef GL_ES
43
+ precision mediump float;
44
+ #endif
45
+
46
+ ${colormaps}
47
+
48
+ // The texture (GL.LUMINANCE & Uint8Array).
49
+ uniform sampler2D uBitmapTexture;
50
+
51
+ // height x width of the data matrix (i.e x and y are flipped compared to the graphics convention)
52
+ uniform vec2 uOrigDataSize;
53
+ uniform vec2 uReshapedDataSize;
54
+
55
+ uniform vec2 tileIJ;
56
+ uniform vec2 dataIJ;
57
+ uniform vec2 numTiles;
58
+
59
+ // What are the dimensions of the texture (width, height)?
60
+ uniform vec2 uTextureSize;
61
+
62
+ // How many consecutive pixels should be aggregated together along each axis?
63
+ uniform vec2 uAggSize;
64
+
65
+ // What are the values of the color scale sliders?
66
+ uniform vec2 uColorScaleRange;
67
+
68
+ // The texture coordinate, varying (interpolated between values set by the vertex shader).
69
+ varying vec2 vTexCoord;
70
+
71
+ vec2 offsetvTexcoord(vec2 coord) {
72
+ float xTileToDataRatio = uTextureSize.x / uOrigDataSize.y;
73
+ float yTileToDataRatio = uTextureSize.y / uOrigDataSize.x;
74
+ vec2 vTexCoordOffset = vec2(
75
+ (tileIJ.y * xTileToDataRatio) + (coord.x * xTileToDataRatio),
76
+ (tileIJ.x * yTileToDataRatio) + ((1. - coord.y) * yTileToDataRatio)
77
+ );
78
+ return vTexCoordOffset;
79
+ }
80
+
81
+ vec2 dataCoordinateFromvTexCoordOffset(vec2 vTexCoordOffset) {
82
+
83
+ // True pixel coordinate on scale of uOrigDataSize
84
+ vec2 viewCoord = vec2(floor(vTexCoordOffset.x * uOrigDataSize.y), floor(vTexCoordOffset.y * uOrigDataSize.x));
85
+ return viewCoord;
86
+ }
87
+
88
+ float getIndexFromViewCoord(vec2 viewCoord) {
89
+ return viewCoord.y * uOrigDataSize.y + viewCoord.x;
90
+ }
91
+
92
+ vec2 transformDataCoordinate(float index) {
93
+ float textureX = (floor( index / uReshapedDataSize.x )) / uReshapedDataSize.x;
94
+ float textureY = (index - (floor( index / uReshapedDataSize.x ) * uReshapedDataSize.x)) / uReshapedDataSize.y;
95
+ vec2 texturedCoord = vec2(textureY, textureX);
96
+ return texturedCoord;
97
+ }
98
+
99
+ void main(void) {
100
+ // Compute 1 pixel in texture coordinates
101
+ vec2 onePixel = vec2(1.0, 1.0) / uTextureSize;
102
+ vec2 vTexCoordOffset = offsetvTexcoord(vTexCoord);
103
+ vec2 viewCoordTransformed = dataCoordinateFromvTexCoordOffset(vTexCoordOffset);
104
+ // Compute (x % aggSizeX, y % aggSizeY).
105
+ // These values will be the number of values to the left / above the current position to consider.
106
+ vec2 modAggSize = vec2(-1.0 * mod(viewCoordTransformed.x, uAggSize.x), -1.0 * mod(viewCoordTransformed.y, uAggSize.y));
107
+ // Take the sum of values along each axis.
108
+ float intensitySum = 0.0;
109
+ vec2 offsetPixels = vec2(0.0, 0.0);
110
+ for(int i = 0; i < 16; i++) {
111
+ // Check to break outer loop early.
112
+ // Uniforms cannot be used as conditions in GLSL for loops.
113
+ if(float(i) >= uAggSize.y) {
114
+ // Done in the y direction.
115
+ break;
116
+ }
117
+
118
+ offsetPixels = vec2(offsetPixels.x, (modAggSize.y + float(i)));
119
+
120
+ for(int j = 0; j < 16; j++) {
121
+ // Check to break inner loop early.
122
+ // Uniforms cannot be used as conditions in GLSL for loops.
123
+ if(float(j) >= uAggSize.x) {
124
+ // Done in the x direction.
125
+ break;
126
+ }
127
+ offsetPixels = vec2((modAggSize.x + float(j)), offsetPixels.y);
128
+ float indexFull = getIndexFromViewCoord(viewCoordTransformed + offsetPixels);
129
+ float index = indexFull - (floor(indexFull / (uReshapedDataSize.x * uReshapedDataSize.y)) * (uReshapedDataSize.x * uReshapedDataSize.y));
130
+ vec2 vTexCoordTransformed = transformDataCoordinate(index);
131
+ intensitySum += texture2D(uBitmapTexture, vTexCoordTransformed).r;
132
+ }
133
+ }
134
+
135
+ // Compute the mean value.
136
+ float intensityMean = intensitySum / (uAggSize.x * uAggSize.y);
137
+ // Re-scale using the color scale slider values.
138
+ float scaledIntensityMean = (intensityMean - uColorScaleRange[0]) / max(0.005, (uColorScaleRange[1] - uColorScaleRange[0]));
139
+
140
+ gl_FragColor = COLORMAP_FUNC(clamp(scaledIntensityMean, 0.0, 1.0));
141
+
142
+ geometry.uv = vTexCoord;
143
+ DECKGL_FILTER_COLOR(gl_FragColor, geometry);
144
+ }
145
+ `;
@@ -0,0 +1,109 @@
1
+ import { COORDINATE_SYSTEM } from '@deck.gl/core'; // eslint-disable-line import/no-extraneous-dependencies
2
+ import { DataFilterExtension } from '@deck.gl/extensions'; // eslint-disable-line import/no-extraneous-dependencies
3
+ import SelectionLayer from './SelectionLayer.js';
4
+
5
+ /**
6
+ * Convert a DeckGL layer ID to a "base" layer ID for selection.
7
+ * @param {string} layerId The layer ID to convert.
8
+ * @returns {string} The base layer ID.
9
+ */
10
+ function getBaseLayerId(layerId) {
11
+ return `base-${layerId}`;
12
+ }
13
+
14
+ /**
15
+ * Convert a DeckGL layer ID to a "selected" layer ID for selection.
16
+ * @param {string} layerId The layer ID to convert.
17
+ * @returns {string} The base layer ID.
18
+ */
19
+ function getSelectedLayerId(layerId) {
20
+ return `selected-${layerId}`;
21
+ }
22
+
23
+ /**
24
+ * Construct DeckGL selection layers.
25
+ * @param {string} tool
26
+ * @param {number} zoom
27
+ * @param {string} cellBaseLayerId
28
+ * @param {function} getCellCoords
29
+ * @param {function} updateCellsSelection
30
+ * @returns {object[]} The array of DeckGL selection layers.
31
+ */
32
+ export function getSelectionLayers(
33
+ tool,
34
+ zoom,
35
+ layerId,
36
+ getCellCoords,
37
+ obsIndex,
38
+ updateCellsSelection,
39
+ cellsQuadTree,
40
+ flipY = false,
41
+ ) {
42
+ if (!tool) {
43
+ return [];
44
+ }
45
+
46
+ const cellBaseLayerId = getBaseLayerId(layerId);
47
+ const editHandlePointRadius = 5 / (zoom + 16);
48
+
49
+ return [new SelectionLayer({
50
+ id: 'selection',
51
+ flipY,
52
+ cellsQuadTree,
53
+ getCellCoords,
54
+ coordinateSystem: COORDINATE_SYSTEM.CARTESIAN,
55
+ selectionType: tool,
56
+ onSelect: ({ pickingInfos }) => {
57
+ const cellIds = pickingInfos.map(i => obsIndex[i]);
58
+ if (updateCellsSelection) {
59
+ updateCellsSelection(cellIds);
60
+ }
61
+ },
62
+ layerIds: [cellBaseLayerId],
63
+ getTentativeFillColor: () => [255, 255, 255, 95],
64
+ getTentativeLineColor: () => [143, 143, 143, 255],
65
+ getTentativeLineDashArray: () => [7, 4],
66
+ lineWidthMinPixels: 2,
67
+ lineWidthMaxPixels: 2,
68
+ getEditHandlePointColor: () => [0xff, 0xff, 0xff, 0xff],
69
+ getEditHandlePointRadius: () => editHandlePointRadius,
70
+ editHandlePointRadiusScale: 1,
71
+ editHandlePointRadiusMinPixels: editHandlePointRadius,
72
+ editHandlePointRadiusMaxPixels: 2 * editHandlePointRadius,
73
+ })];
74
+ }
75
+
76
+ /**
77
+ * Get deck.gl layer props for selection overlays.
78
+ * @param {object} props
79
+ * @returns {object} Object with two properties,
80
+ * overlay: overlayProps, base: baseProps,
81
+ * where the values are deck.gl layer props.
82
+ */
83
+ export function overlayBaseProps(props) {
84
+ const {
85
+ id, getColor, data, isSelected, ...rest
86
+ } = props;
87
+ return {
88
+ overlay: {
89
+ id: getSelectedLayerId(id),
90
+ getFillColor: getColor,
91
+ getLineColor: getColor,
92
+ data,
93
+ getFilterValue: isSelected,
94
+ extensions: [new DataFilterExtension({ filterSize: 1 })],
95
+ filterRange: [1, 1],
96
+ ...rest,
97
+ },
98
+ base: {
99
+ id: getBaseLayerId(id),
100
+ getLineColor: getColor,
101
+ getFillColor: getColor,
102
+ // Alternatively: contrast outlines with solids:
103
+ // getLineColor: getColor,
104
+ // getFillColor: [255, 255, 255],
105
+ data: data.slice(),
106
+ ...rest,
107
+ },
108
+ };
109
+ }
package/src/viv.js ADDED
@@ -0,0 +1,20 @@
1
+ export {
2
+ ZarrPixelSource,
3
+ loadOmeTiff,
4
+ loadOmeZarr,
5
+ XRLayer,
6
+ getChannelStats,
7
+ RENDERING_MODES,
8
+ MAX_CHANNELS,
9
+ getDefaultInitialViewState,
10
+ ScaleBarLayer,
11
+ MultiscaleImageLayer,
12
+ AdditiveColormapExtension,
13
+ ColorPaletteExtension,
14
+ ImageLayer,
15
+ VolumeLayer,
16
+ AdditiveColormap3DExtensions,
17
+ ColorPalette3DExtensions,
18
+ // TODO: deprecated
19
+ DTYPE_VALUES,
20
+ } from '@hms-dbmi/viv';
@@ -1,2 +0,0 @@
1
- import SelectionExtension from './SelectionExtension';
2
- export default SelectionExtension;
@@ -1,109 +0,0 @@
1
- import { Matrix4 } from 'math.gl';
2
- import { getChannelStats } from './viv';
3
- async function getSingleSelectionStats2D({ loader, selection }) {
4
- const data = Array.isArray(loader) ? loader[loader.length - 1] : loader;
5
- const raster = await data.getRaster({ selection });
6
- const selectionStats = getChannelStats(raster.data);
7
- const { domain, contrastLimits: slider } = selectionStats;
8
- return { domain, slider };
9
- }
10
- async function getSingleSelectionStats3D({ loader, selection }) {
11
- const lowResSource = loader[loader.length - 1];
12
- const { shape, labels } = lowResSource;
13
- // eslint-disable-next-line no-bitwise
14
- const sizeZ = shape[labels.indexOf('z')] >> (loader.length - 1);
15
- const raster0 = await lowResSource.getRaster({
16
- selection: { ...selection, z: 0 },
17
- });
18
- const rasterMid = await lowResSource.getRaster({
19
- selection: { ...selection, z: Math.floor(sizeZ / 2) },
20
- });
21
- const rasterTop = await lowResSource.getRaster({
22
- selection: { ...selection, z: Math.max(0, sizeZ - 1) },
23
- });
24
- const stats0 = getChannelStats(raster0.data);
25
- const statsMid = getChannelStats(rasterMid.data);
26
- const statsTop = getChannelStats(rasterTop.data);
27
- return {
28
- domain: [
29
- Math.min(stats0.domain[0], statsMid.domain[0], statsTop.domain[0]),
30
- Math.max(stats0.domain[1], statsMid.domain[1], statsTop.domain[1]),
31
- ],
32
- slider: [
33
- Math.min(stats0.contrastLimits[0], statsMid.contrastLimits[0], statsTop.contrastLimits[0]),
34
- Math.max(stats0.contrastLimits[1], statsMid.contrastLimits[1], statsTop.contrastLimits[1]),
35
- ],
36
- };
37
- }
38
- /**
39
- * Get bounding cube for a given loader i.e [[0, width], [0, height], [0, depth]]
40
- * @param {Object} loader PixelSource|PixelSource[]
41
- * @param {[]} selection Selection for stats.
42
- * @param {boolean} use3d Whether or not to get 3d stats.
43
- * @returns {Object} { domains, sliders }
44
- */
45
- export const getSingleSelectionStats = async ({ loader, selection, use3d }) => {
46
- const getStats = use3d
47
- ? getSingleSelectionStats3D
48
- : getSingleSelectionStats2D;
49
- return getStats({ loader, selection });
50
- };
51
- export const getMultiSelectionStats = async ({ loader, selections, use3d }) => {
52
- const stats = await Promise.all(selections.map(selection => getSingleSelectionStats({ loader, selection, use3d })));
53
- const domains = stats.map(stat => stat.domain);
54
- const sliders = stats.map(stat => stat.slider);
55
- return { domains, sliders };
56
- };
57
- /**
58
- * Get physical size scaling Matrix4
59
- * @param {Object} loader PixelSource
60
- * @returns {Object} matrix
61
- */
62
- export function getPhysicalSizeScalingMatrix(loader) {
63
- const { x, y, z } = loader?.meta?.physicalSizes ?? {};
64
- if (x?.size && y?.size && z?.size) {
65
- const min = Math.min(z.size, x.size, y.size);
66
- const ratio = [x.size / min, y.size / min, z.size / min];
67
- return new Matrix4().scale(ratio);
68
- }
69
- return new Matrix4().identity();
70
- }
71
- /**
72
- * Get bounding cube for a given loader
73
- * @param {Object} loader PixelSource|PixelSource[]
74
- * @returns {Array} [0, width], [0, height], [0, depth]]
75
- */
76
- export function getBoundingCube(loader) {
77
- const source = Array.isArray(loader) ? loader[0] : loader;
78
- const { shape, labels } = source;
79
- const physicalSizeScalingMatrix = getPhysicalSizeScalingMatrix(source);
80
- const xSlice = [0, physicalSizeScalingMatrix[0] * shape[labels.indexOf('x')]];
81
- const ySlice = [0, physicalSizeScalingMatrix[5] * shape[labels.indexOf('y')]];
82
- const zSlice = [
83
- 0,
84
- physicalSizeScalingMatrix[10] * shape[labels.indexOf('z')],
85
- ];
86
- return [xSlice, ySlice, zSlice];
87
- }
88
- export function abbreviateNumber(value) {
89
- // Return an abbreviated representation of value, in 5 characters or less.
90
- const maxLength = 5;
91
- let maxNaiveDigits = maxLength;
92
- /* eslint-disable no-plusplus */
93
- if (!Number.isInteger(value)) {
94
- --maxNaiveDigits;
95
- } // Wasted on "."
96
- if (value < 1) {
97
- --maxNaiveDigits;
98
- } // Wasted on "0."
99
- /* eslint-disable no-plusplus */
100
- const naive = Intl.NumberFormat('en-US', {
101
- maximumSignificantDigits: maxNaiveDigits,
102
- useGrouping: false,
103
- }).format(value);
104
- if (naive.length <= maxLength)
105
- return naive;
106
- // "e+9" consumes 3 characters, so if we even had two significant digits,
107
- // it would take take us to six characters, including the decimal point.
108
- return value.toExponential(0);
109
- }