@vitessce/vit-s 2.0.0-beta.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 (91) hide show
  1. package/LICENSE +21 -0
  2. package/dist/CallbackPublisher.js +68 -0
  3. package/dist/LoadingIndicator.js +27 -0
  4. package/dist/TitleInfo.js +151 -0
  5. package/dist/VitS.js +113 -0
  6. package/dist/Vitessce.integration.test.js +36 -0
  7. package/dist/Vitessce.js +101 -0
  8. package/dist/VitessceGrid.js +55 -0
  9. package/dist/VitessceGrid.test.js +36 -0
  10. package/dist/Warning.js +45 -0
  11. package/dist/classNames.js +8 -0
  12. package/dist/component-registry.js +16 -0
  13. package/dist/data/AbstractLoader.js +35 -0
  14. package/dist/data/AbstractTwoStepLoader.js +7 -0
  15. package/dist/data/LoaderResult.js +7 -0
  16. package/dist/data/index.js +3 -0
  17. package/dist/data/loader-registry.js +15 -0
  18. package/dist/data-hook-utils.js +175 -0
  19. package/dist/data-hooks.js +241 -0
  20. package/dist/errors/AbstractLoaderError.js +13 -0
  21. package/dist/errors/DataSourceFetchError.js +13 -0
  22. package/dist/errors/DatasetNotFoundError.js +17 -0
  23. package/dist/errors/LoaderNotFoundError.js +17 -0
  24. package/dist/errors/LoaderValidationError.js +15 -0
  25. package/dist/errors/OptionsValidationError.js +15 -0
  26. package/dist/errors/index.js +6 -0
  27. package/dist/export-utils.js +70 -0
  28. package/dist/export-utils.test.js +66 -0
  29. package/dist/file-options-schemas-legacy.js +136 -0
  30. package/dist/file-options-schemas-legacy.test.js +126 -0
  31. package/dist/file-options-schemas.js +322 -0
  32. package/dist/file-options-schemas.test.js +23 -0
  33. package/dist/hooks.js +215 -0
  34. package/dist/index.js +18 -0
  35. package/dist/joint-file-types-legacy.js +278 -0
  36. package/dist/joint-file-types-legacy.test.js +400 -0
  37. package/dist/joint-file-types.js +148 -0
  38. package/dist/joint-file-types.test.js +139 -0
  39. package/dist/loader-registry.js +98 -0
  40. package/dist/plugins.js +154 -0
  41. package/dist/plugins.test.fixtures.js +76 -0
  42. package/dist/plugins.test.js +30 -0
  43. package/dist/schemas/PrettyJsonSchema.js +34 -0
  44. package/dist/schemas/config-0.1.0.schema.json +84 -0
  45. package/dist/schemas/config-1.0.0.schema.json +733 -0
  46. package/dist/schemas/config-1.0.1.schema.json +909 -0
  47. package/dist/schemas/config-1.0.10.schema.json +969 -0
  48. package/dist/schemas/config-1.0.11.schema.json +990 -0
  49. package/dist/schemas/config-1.0.12.schema.json +997 -0
  50. package/dist/schemas/config-1.0.13.schema.json +1013 -0
  51. package/dist/schemas/config-1.0.14.schema.json +1048 -0
  52. package/dist/schemas/config-1.0.15.schema.json +1048 -0
  53. package/dist/schemas/config-1.0.15.schema.test.js +22 -0
  54. package/dist/schemas/config-1.0.2.schema.json +910 -0
  55. package/dist/schemas/config-1.0.3.schema.json +910 -0
  56. package/dist/schemas/config-1.0.4.schema.json +949 -0
  57. package/dist/schemas/config-1.0.5.schema.json +949 -0
  58. package/dist/schemas/config-1.0.6.schema.json +949 -0
  59. package/dist/schemas/config-1.0.7.schema.json +949 -0
  60. package/dist/schemas/config-1.0.8.schema.json +965 -0
  61. package/dist/schemas/config-1.0.9.schema.json +965 -0
  62. package/dist/schemas/obsSets.schema.js +195 -0
  63. package/dist/schemas/obsSets.schema.json +194 -0
  64. package/dist/schemas/obsSetsTabular.schema.js +38 -0
  65. package/dist/schemas/obsSetsTabular.schema.json +37 -0
  66. package/dist/schemas/raster.schema.js +120 -0
  67. package/dist/schemas/raster.schema.json +119 -0
  68. package/dist/schemas/schema.test-old.js +50 -0
  69. package/dist/schemas/schema.test.js +46 -0
  70. package/dist/schemas.js +4 -0
  71. package/dist/shared-mui/components.js +35 -0
  72. package/dist/shared-mui/container.js +211 -0
  73. package/dist/shared-mui/styles.js +63 -0
  74. package/dist/shared-plot-options/CellColorEncodingOption.js +18 -0
  75. package/dist/shared-plot-options/OptionSelect.js +12 -0
  76. package/dist/shared-plot-options/OptionsContainer.js +12 -0
  77. package/dist/shared-plot-options/index.js +4 -0
  78. package/dist/shared-plot-options/styles.js +48 -0
  79. package/dist/state/hooks.js +550 -0
  80. package/dist/view-config-upgraders.js +525 -0
  81. package/dist/view-config-utils.js +286 -0
  82. package/dist/view-config-utils.test.fixtures.js +765 -0
  83. package/dist/view-config-utils.test.js +66 -0
  84. package/dist/view-config-versions.js +47 -0
  85. package/dist/vitessce-grid-layout/VitessceGridLayout.js +96 -0
  86. package/dist/vitessce-grid-layout/VitessceGridLayout.test.js +40 -0
  87. package/dist/vitessce-grid-layout/index.js +1 -0
  88. package/dist/vitessce-grid-layout/layout-utils.js +61 -0
  89. package/dist/vitessce-grid-layout/layout-utils.test.js +146 -0
  90. package/dist/vitessce-grid-utils.js +140 -0
  91. package/package.json +43 -0
@@ -0,0 +1,322 @@
1
+ import Ajv from 'ajv';
2
+ export function validateOptions(optionsSchema, options) {
3
+ const validate = new Ajv().compile(optionsSchema);
4
+ const valid = validate(options || null);
5
+ if (!valid) {
6
+ console.warn(JSON.stringify(validate.errors, null, 2));
7
+ throw new Error(`File definition options failed schema validation (${optionsSchema.title})`);
8
+ }
9
+ return true;
10
+ }
11
+ export const emptySchema = {
12
+ $schema: 'http://json-schema.org/draft-07/schema#',
13
+ $id: 'https://github.com/vitessce/vitessce/#empty-options',
14
+ title: 'Empty options',
15
+ oneOf: [
16
+ { type: 'null' },
17
+ ],
18
+ };
19
+ const sharedDefinitions = {
20
+ annDataObs: {
21
+ type: 'object',
22
+ additionalProperties: false,
23
+ required: ['path'],
24
+ properties: {
25
+ path: { type: 'string' },
26
+ },
27
+ },
28
+ annDataObsm: {
29
+ type: 'object',
30
+ additionalProperties: false,
31
+ required: ['path'],
32
+ properties: {
33
+ path: { type: 'string' },
34
+ dims: {
35
+ type: 'array',
36
+ description: 'Which indices of the obsm object to take for a scatterplot, allowing for, for example, different PCs from obsm/X_pca',
37
+ items: { type: 'number' },
38
+ },
39
+ },
40
+ },
41
+ annDataConvenienceObsLabelsItem: {
42
+ type: 'object',
43
+ additionalProperties: false,
44
+ required: ['path', 'obsLabelsType'],
45
+ properties: {
46
+ path: { type: 'string' },
47
+ obsLabelsType: { type: 'string' },
48
+ },
49
+ },
50
+ annDataConvenienceFeatureLabelsItem: {
51
+ type: 'object',
52
+ additionalProperties: false,
53
+ required: ['path', 'featureLabelsType'],
54
+ properties: {
55
+ path: { type: 'string' },
56
+ featureLabelsType: { type: 'string' },
57
+ },
58
+ },
59
+ annDataConvenienceObsEmbeddingItem: {
60
+ type: 'object',
61
+ additionalProperties: false,
62
+ required: ['path', 'embeddingType'],
63
+ properties: {
64
+ path: { type: 'string' },
65
+ dims: {
66
+ type: 'array',
67
+ description: 'Which indices of the obsm object to take for a scatterplot, allowing for, for example, different PCs from obsm/X_pca',
68
+ items: { type: 'number' },
69
+ },
70
+ embeddingType: { type: 'string' },
71
+ },
72
+ },
73
+ annDataObsLabels: { $ref: '#/definitions/annDataObs' },
74
+ annDataFeatureLabels: { $ref: '#/definitions/annDataObs' },
75
+ annDataObsFeatureMatrix: {
76
+ type: 'object',
77
+ description: 'Options for the obsFeatureMatrix.anndata.zarr file type.',
78
+ additionalProperties: false,
79
+ required: ['path'],
80
+ properties: {
81
+ path: { type: 'string' },
82
+ featureFilterPath: {
83
+ type: 'string',
84
+ description: 'If the feature index should be filtered, put a boolean column here (analogous to the previous geneFilter option). e.g., var/in_obsm_X_small_matrix',
85
+ },
86
+ initialFeatureFilterPath: {
87
+ type: 'string',
88
+ description: 'If only a subset of the matrix should be loaded initially, put a boolean column along the feature axis here (analogous to the previous matrixGeneFilter option). e.g., var/highly_variable',
89
+ },
90
+ },
91
+ },
92
+ annDataObsSets: {
93
+ type: 'array',
94
+ description: 'Options for the obsSets.anndata.zarr file type.',
95
+ items: {
96
+ type: 'object',
97
+ additionalProperties: false,
98
+ required: ['name', 'path'],
99
+ properties: {
100
+ name: {
101
+ type: 'string',
102
+ description: "The display name for the set, like 'Cell Type' or 'Louvain.'",
103
+ },
104
+ path: {
105
+ oneOf: [
106
+ {
107
+ type: 'string',
108
+ description: "The location in the AnnData store for the set, like 'obs/louvain' or 'obs/celltype.'",
109
+ },
110
+ {
111
+ type: 'array',
112
+ items: { type: 'string' },
113
+ description: 'An array of locations in the AnnData store for a hierarchy of set names, from coarse to fine levels.',
114
+ },
115
+ ],
116
+ },
117
+ scorePath: {
118
+ oneOf: [
119
+ {
120
+ type: 'string',
121
+ description: "The location in the AnnData store for the set confidence scores, like 'obs/celltype_prediction_score.'",
122
+ },
123
+ ],
124
+ },
125
+ },
126
+ },
127
+ },
128
+ annDataObsLocations: { $ref: '#/definitions/annDataObsm' },
129
+ annDataObsEmbedding: { $ref: '#/definitions/annDataObsm' },
130
+ annDataObsSegmentations: { $ref: '#/definitions/annDataObs' },
131
+ };
132
+ /**
133
+ * Options schemas for atomic file types.
134
+ */
135
+ // AnnData
136
+ export const obsEmbeddingAnndataSchema = {
137
+ $schema: 'http://json-schema.org/draft-07/schema#',
138
+ $id: 'https://github.com/vitessce/vitessce/#obsEmbedding-anndata-zarr-options',
139
+ title: 'obsEmbedding.anndata.zarr options',
140
+ definitions: sharedDefinitions,
141
+ $ref: '#/definitions/annDataObsEmbedding',
142
+ };
143
+ export const obsLocationsAnndataSchema = {
144
+ $schema: 'http://json-schema.org/draft-07/schema#',
145
+ $id: 'https://github.com/vitessce/vitessce/#obsLocations-anndata-zarr-options',
146
+ title: 'obsLocations.anndata.zarr options',
147
+ definitions: sharedDefinitions,
148
+ $ref: '#/definitions/annDataObsLocations',
149
+ };
150
+ export const obsSegmentationsAnndataSchema = {
151
+ $schema: 'http://json-schema.org/draft-07/schema#',
152
+ $id: 'https://github.com/vitessce/vitessce/#obsSegmentations-anndata-zarr-options',
153
+ title: 'obsSegmentations.anndata.zarr options',
154
+ definitions: sharedDefinitions,
155
+ $ref: '#/definitions/annDataObsSegmentations',
156
+ };
157
+ export const obsSetsAnndataSchema = {
158
+ $schema: 'http://json-schema.org/draft-07/schema#',
159
+ $id: 'https://github.com/vitessce/vitessce/#obsSets-anndata-zarr-options',
160
+ title: 'obsSets.anndata.zarr options',
161
+ definitions: sharedDefinitions,
162
+ $ref: '#/definitions/annDataObsSets',
163
+ };
164
+ export const obsFeatureMatrixAnndataSchema = {
165
+ $schema: 'http://json-schema.org/draft-07/schema#',
166
+ $id: 'https://github.com/vitessce/vitessce/#obsFeatureMatrix-anndata-zarr-options',
167
+ title: 'obsFeatureMatrix.anndata.zarr options',
168
+ definitions: sharedDefinitions,
169
+ $ref: '#/definitions/annDataObsFeatureMatrix',
170
+ };
171
+ export const obsLabelsAnndataSchema = {
172
+ $schema: 'http://json-schema.org/draft-07/schema#',
173
+ $id: 'https://github.com/vitessce/vitessce/#obsLabels-anndata-zarr-options',
174
+ title: 'obsLabels.anndata.zarr options',
175
+ definitions: sharedDefinitions,
176
+ $ref: '#/definitions/annDataObsLabels',
177
+ };
178
+ export const featureLabelsAnndataSchema = {
179
+ $schema: 'http://json-schema.org/draft-07/schema#',
180
+ $id: 'https://github.com/vitessce/vitessce/#featureLabels-anndata-zarr-options',
181
+ title: 'featureLabels.anndata.zarr options',
182
+ definitions: sharedDefinitions,
183
+ $ref: '#/definitions/annDataFeatureLabels',
184
+ };
185
+ // CSV
186
+ export const obsEmbeddingCsvSchema = {
187
+ $schema: 'http://json-schema.org/draft-07/schema#',
188
+ $id: 'https://github.com/vitessce/vitessce/#obsEmbedding-csv-options',
189
+ title: 'obsEmbedding.csv options',
190
+ type: 'object',
191
+ required: ['obsIndex', 'obsEmbedding'],
192
+ properties: {
193
+ obsIndex: { type: 'string' },
194
+ obsEmbedding: {
195
+ type: 'array',
196
+ items: { type: 'string' },
197
+ minItems: 2,
198
+ maxItems: 2,
199
+ },
200
+ },
201
+ };
202
+ export const obsLocationsCsvSchema = {
203
+ $schema: 'http://json-schema.org/draft-07/schema#',
204
+ $id: 'https://github.com/vitessce/vitessce/#obsLocations-csv-options',
205
+ title: 'obsLocations.csv options',
206
+ type: 'object',
207
+ required: ['obsIndex', 'obsLocations'],
208
+ properties: {
209
+ obsIndex: { type: 'string' },
210
+ obsLocations: {
211
+ type: 'array',
212
+ items: { type: 'string' },
213
+ minItems: 2,
214
+ maxItems: 2,
215
+ },
216
+ },
217
+ };
218
+ export const obsLabelsCsvSchema = {
219
+ $schema: 'http://json-schema.org/draft-07/schema#',
220
+ $id: 'https://github.com/vitessce/vitessce/#obsLabels-csv-options',
221
+ title: 'obsLabels.csv options',
222
+ type: 'object',
223
+ required: ['obsIndex', 'obsLabels'],
224
+ properties: {
225
+ obsIndex: { type: 'string' },
226
+ obsLabels: { type: 'string' },
227
+ },
228
+ };
229
+ export const featureLabelsCsvSchema = {
230
+ $schema: 'http://json-schema.org/draft-07/schema#',
231
+ $id: 'https://github.com/vitessce/vitessce/#featureLabels-csv-options',
232
+ title: 'featureLabels.csv options',
233
+ type: 'object',
234
+ required: ['featureIndex', 'featureLabels'],
235
+ properties: {
236
+ featureIndex: { type: 'string' },
237
+ featureLabels: { type: 'string' },
238
+ },
239
+ };
240
+ export const obsSetsCsvSchema = {
241
+ $schema: 'http://json-schema.org/draft-07/schema#',
242
+ $id: 'https://github.com/vitessce/vitessce/#obsLabels-csv-options',
243
+ title: 'obsLabels.csv options',
244
+ type: 'object',
245
+ additionalProperties: false,
246
+ required: ['obsIndex', 'obsSets'],
247
+ properties: {
248
+ obsIndex: { type: 'string' },
249
+ obsSets: {
250
+ type: 'array',
251
+ items: {
252
+ type: 'object',
253
+ additionalProperties: false,
254
+ required: ['name', 'column'],
255
+ properties: {
256
+ name: {
257
+ type: 'string',
258
+ description: "The display name for the set, like 'Cell Type' or 'Louvain'",
259
+ },
260
+ column: {
261
+ oneOf: [
262
+ {
263
+ type: 'string',
264
+ description: "The column for the set, like 'cell_type'",
265
+ },
266
+ {
267
+ type: 'array',
268
+ items: { type: 'string' },
269
+ description: 'An array of columns for a hierarchy of set names, from coarse to fine levels.',
270
+ },
271
+ ],
272
+ },
273
+ scoreColumn: {
274
+ oneOf: [
275
+ {
276
+ type: 'string',
277
+ description: "The column for the set confidence scores, like 'celltype_prediction_score'",
278
+ },
279
+ ],
280
+ },
281
+ },
282
+ },
283
+ },
284
+ },
285
+ };
286
+ /**
287
+ * Options schemas for joint file types.
288
+ */
289
+ export const anndataZarrSchema = {
290
+ $schema: 'http://json-schema.org/draft-07/schema#',
291
+ $id: 'https://github.com/vitessce/vitessce/#anndata-zarr-options',
292
+ title: 'anndata.zarr options',
293
+ definitions: sharedDefinitions,
294
+ type: 'object',
295
+ minProperties: 1,
296
+ additionalProperties: false,
297
+ required: [],
298
+ properties: {
299
+ obsLabels: {
300
+ oneOf: [
301
+ { $ref: '#/definitions/annDataObsLabels' },
302
+ { type: 'array', items: { $ref: '#/definitions/annDataConvenienceObsLabelsItem' } },
303
+ ],
304
+ },
305
+ featureLabels: {
306
+ oneOf: [
307
+ { $ref: '#/definitions/annDataFeatureLabels' },
308
+ { type: 'array', items: { $ref: '#/definitions/annDataConvenienceFeatureLabelsItem' } },
309
+ ],
310
+ },
311
+ obsFeatureMatrix: { $ref: '#/definitions/annDataObsFeatureMatrix' },
312
+ obsSets: { $ref: '#/definitions/annDataObsSets' },
313
+ obsLocations: { $ref: '#/definitions/annDataObsLocations' },
314
+ obsSegmentations: { $ref: '#/definitions/annDataObsSegmentations' },
315
+ obsEmbedding: {
316
+ oneOf: [
317
+ { $ref: '#/definitions/annDataObsEmbedding' },
318
+ { type: 'array', items: { $ref: '#/definitions/annDataConvenienceObsEmbeddingItem' } },
319
+ ],
320
+ },
321
+ },
322
+ };
@@ -0,0 +1,23 @@
1
+ import { expandAnndataZarr, } from './joint-file-types';
2
+ describe('src/app/file-options-schemas.js', () => {
3
+ describe('Options validation for joint file type expansion functions', () => {
4
+ it('anndata.zarr with invalid options fails validation', () => {
5
+ expect(() => expandAnndataZarr({
6
+ fileType: 'anndata.zarr',
7
+ url: 'http://localhost:8000/anndata.zarr',
8
+ options: {
9
+ obsFeatureMatrix: 1,
10
+ },
11
+ })).toThrow();
12
+ });
13
+ it('anndata.zarr with extra options fails validation', () => {
14
+ expect(() => expandAnndataZarr({
15
+ fileType: 'anndata.zarr',
16
+ url: 'http://localhost:8000/anndata.zarr',
17
+ options: {
18
+ bad: 'bad',
19
+ },
20
+ })).toThrow();
21
+ });
22
+ });
23
+ });
package/dist/hooks.js ADDED
@@ -0,0 +1,215 @@
1
+ import { useRef, useState, useEffect, useCallback, useMemo, } from 'react';
2
+ import debounce from 'lodash/debounce';
3
+ import every from 'lodash/every';
4
+ import { capitalize, fromEntries } from '@vitessce/utils';
5
+ import { useGridResize, useEmitGridResize } from './state/hooks';
6
+ import { VITESSCE_CONTAINER } from './classNames';
7
+ function getWindowDimensions() {
8
+ const { innerWidth: width, innerHeight: height } = window;
9
+ return {
10
+ width,
11
+ height,
12
+ };
13
+ }
14
+ export function useVitessceContainer(ref) {
15
+ return useCallback(() => {
16
+ if (ref.current) {
17
+ return ref.current.closest(`.${VITESSCE_CONTAINER}`);
18
+ }
19
+ return null;
20
+ }, [ref]);
21
+ }
22
+ /**
23
+ * Custom hook, gets the full window dimensions.
24
+ * @returns {array} `[width, height]` where width and height
25
+ * are numbers.
26
+ */
27
+ export function useWindowDimensions() {
28
+ const [windowDimensions, setWindowDimensions] = useState(getWindowDimensions());
29
+ useEffect(() => {
30
+ function handleResize() {
31
+ setWindowDimensions(getWindowDimensions());
32
+ }
33
+ const onResizeDebounced = debounce(handleResize, 100, { trailing: true });
34
+ window.addEventListener('resize', onResizeDebounced);
35
+ return () => window.removeEventListener('resize', onResizeDebounced);
36
+ }, []);
37
+ return windowDimensions;
38
+ }
39
+ /**
40
+ * Custom hook, subscribes to GRID_RESIZE and window resize events.
41
+ * @returns {array} `[width, height, containerRef]` where width and height
42
+ * are numbers and containerRef is a React ref.
43
+ */
44
+ export function useGridItemSize() {
45
+ const containerRef = useRef();
46
+ const [height, setHeight] = useState();
47
+ const [width, setWidth] = useState();
48
+ const resizeCount = useGridResize();
49
+ const incrementResizeCount = useEmitGridResize();
50
+ // On window resize events, increment the grid resize count.
51
+ useEffect(() => {
52
+ function onWindowResize() {
53
+ incrementResizeCount();
54
+ }
55
+ const onResizeDebounced = debounce(onWindowResize, 100, { trailing: true });
56
+ window.addEventListener('resize', onResizeDebounced);
57
+ onWindowResize();
58
+ return () => {
59
+ window.removeEventListener('resize', onResizeDebounced);
60
+ };
61
+ }, [incrementResizeCount]);
62
+ // On new grid resize counts, re-compute the component
63
+ // width/height.
64
+ useEffect(() => {
65
+ if (!containerRef.current)
66
+ return;
67
+ const container = containerRef.current;
68
+ const containerRect = container.getBoundingClientRect();
69
+ setHeight(containerRect.height);
70
+ setWidth(containerRect.width);
71
+ }, [resizeCount]);
72
+ return [width, height, containerRef];
73
+ }
74
+ /**
75
+ * Custom hook, subscribes to GRID_RESIZE and window resize events.
76
+ * @returns {array} `[width, height, deckRef]` where width and height
77
+ * are numbers and deckRef is a React ref to be used with
78
+ * a <DeckGL/> element (or a forwardRef to one).
79
+ */
80
+ export function useDeckCanvasSize() {
81
+ const deckRef = useRef();
82
+ const [height, setHeight] = useState();
83
+ const [width, setWidth] = useState();
84
+ const resizeCount = useGridResize();
85
+ const incrementResizeCount = useEmitGridResize();
86
+ // On window resize events, increment the grid resize count.
87
+ useEffect(() => {
88
+ function onWindowResize() {
89
+ incrementResizeCount();
90
+ }
91
+ const onResizeDebounced = debounce(onWindowResize, 100, { trailing: true });
92
+ window.addEventListener('resize', onResizeDebounced);
93
+ onWindowResize();
94
+ return () => {
95
+ window.removeEventListener('resize', onResizeDebounced);
96
+ };
97
+ }, [incrementResizeCount]);
98
+ // On new grid resize counts, re-compute the DeckGL canvas
99
+ // width/height.
100
+ useEffect(() => {
101
+ if (!deckRef.current)
102
+ return;
103
+ const { canvas } = deckRef.current.deck;
104
+ const canvasRect = canvas.getBoundingClientRect();
105
+ setHeight(canvasRect.height);
106
+ setWidth(canvasRect.width);
107
+ }, [resizeCount]);
108
+ return [width, height, deckRef];
109
+ }
110
+ /**
111
+ * This hook handles a boolean isReady value,
112
+ * which only returns true once every item in the
113
+ * input list has been marked as "ready".
114
+ * @param {string[]} statusValues The items to wait on.
115
+ * @returns {boolean} Whether the status values are all success.
116
+ */
117
+ export function useReady(statusValues) {
118
+ return useMemo(() => every(statusValues, val => val === 'success'), statusValues);
119
+ }
120
+ /**
121
+ * This hook helps manage a list of URLs.
122
+ * @param {object} loaders The loaders dependency.
123
+ * @param {string} dataset The dataset UID dependency.
124
+ * @returns {array} An array
125
+ * [urls, addUrl]
126
+ * where urls is the array of URL objects,
127
+ * and addUrl is a function for adding a URL to the array.
128
+ */
129
+ export function useUrls(loaders, dataset) {
130
+ const [urls, setUrls] = useState([]);
131
+ const addUrl = useCallback((url, name) => {
132
+ if (url) {
133
+ setUrls(prev => ([...prev, { url, name }]));
134
+ }
135
+ }, [setUrls]);
136
+ useEffect(() => {
137
+ setUrls([]);
138
+ }, [loaders, dataset]);
139
+ return [urls, addUrl];
140
+ }
141
+ /**
142
+ * Custom hook, subscribes to the width and height of the closest .vitessce-container
143
+ * element and updates upon window resize events.
144
+ * @param {Ref} ref A React ref object within the `.vitessce-container`.
145
+ * @returns {array} `[width, height]` where width and height
146
+ * are numbers.
147
+ */
148
+ export function useClosestVitessceContainerSize(ref) {
149
+ const [height, setHeight] = useState();
150
+ const [width, setWidth] = useState();
151
+ useEffect(() => {
152
+ function onWindowResize() {
153
+ if (ref.current) {
154
+ const { clientHeight: componentHeight, clientWidth: componentWidth, } = ref.current.closest(`.${VITESSCE_CONTAINER}`);
155
+ setWidth(componentWidth);
156
+ setHeight(componentHeight);
157
+ }
158
+ }
159
+ const onResizeDebounced = debounce(onWindowResize, 100, { trailing: true });
160
+ window.addEventListener('resize', onResizeDebounced);
161
+ onWindowResize();
162
+ return () => {
163
+ window.removeEventListener('resize', onResizeDebounced);
164
+ };
165
+ }, [ref]);
166
+ return [width, height];
167
+ }
168
+ export function useExpressionValueGetter({ instanceObsIndex, matrixObsIndex, expressionData }) {
169
+ // Get a mapping from cell ID to row index in the gene expression matrix.
170
+ // Since the two obsIndices (instanceObsIndex = the obsIndex from obsEmbedding)
171
+ // may be ordered differently (matrixObsIndex = the obsIndex from obsFeatureMatrix),
172
+ // we need a way to look up an obsFeatureMatrix obsIndex index
173
+ // given an obsEmbedding obsIndex index.
174
+ const toMatrixIndexMap = useMemo(() => {
175
+ if (instanceObsIndex && matrixObsIndex) {
176
+ const matrixIndexMap = new Map(matrixObsIndex.map((key, i) => ([key, i])));
177
+ return instanceObsIndex.map(key => matrixIndexMap.get(key));
178
+ }
179
+ return null;
180
+ }, [instanceObsIndex, matrixObsIndex]);
181
+ // Set up a getter function for gene expression values, to be used
182
+ // by the DeckGL layer to obtain values for instanced attributes.
183
+ const getExpressionValue = useCallback((entry, { index: instanceIndex }) => {
184
+ if (toMatrixIndexMap && expressionData && expressionData[0]) {
185
+ const rowIndex = toMatrixIndexMap[instanceIndex];
186
+ const val = expressionData[0][rowIndex];
187
+ return val;
188
+ }
189
+ return 0;
190
+ }, [toMatrixIndexMap, expressionData]);
191
+ return getExpressionValue;
192
+ }
193
+ export function useGetObsInfo(obsType, obsLabelsTypes, obsLabelsData, obsSetsMembership) {
194
+ return useCallback((obsId) => {
195
+ if (obsId) {
196
+ const obsMembership = obsSetsMembership?.get(obsId) || [];
197
+ return {
198
+ [`${capitalize(obsType)} ID`]: obsId,
199
+ ...fromEntries(obsMembership.flatMap(path => path.slice(1).map((pathEl, elLevel) => ([
200
+ `${path[0]}${path.length > 2 ? ` L${elLevel + 1}` : ''}`,
201
+ pathEl,
202
+ ])))),
203
+ ...fromEntries(Object.entries(obsLabelsTypes).map(([scopeKey, obsLabelsType]) => ([
204
+ obsLabelsType,
205
+ obsLabelsData?.[scopeKey]?.obsLabels?.[
206
+ // TODO: Maybe all loaders that return obsIndex should also return an obsIndexMap
207
+ // with keys: obsId, values: obsIdx
208
+ // which would avoid the indexOf calls.
209
+ obsLabelsData?.[scopeKey]?.obsIndex?.indexOf(obsId)],
210
+ ])).filter(([obsLabelsType]) => Boolean(obsLabelsType))),
211
+ };
212
+ }
213
+ return null;
214
+ }, [obsType, obsLabelsTypes, obsLabelsData, obsSetsMembership]);
215
+ }
package/dist/index.js ADDED
@@ -0,0 +1,18 @@
1
+ export { VitS } from './VitS';
2
+ export { TitleInfo } from './TitleInfo';
3
+ export { PopperMenu } from './shared-mui/components';
4
+ export { registerPluginViewType, registerPluginCoordinationType, registerPluginFileType, } from './plugins';
5
+ // For plugin view types:
6
+ export { useReady, useUrls, useVitessceContainer, useDeckCanvasSize, useExpressionValueGetter, useGetObsInfo, useClosestVitessceContainerSize, useWindowDimensions, useGridItemSize, } from './hooks';
7
+ export { useCoordination, useMultiDatasetCoordination, useDatasetUids, useLoaders, useMatchingLoader, useViewConfigStore, useViewConfigStoreApi, useComponentHover, useSetComponentHover, useComponentViewInfo, useSetComponentViewInfo, useWarning, useSetWarning, useAuxiliaryCoordination, useComponentLayout, } from './state/hooks';
8
+ export { useDescription, useImageData, useObsSetsData, useObsEmbeddingData, useFeatureSelection, useObsFeatureMatrixIndices, useMultiObsLabels, useObsLocationsData, useObsSegmentationsData, useNeighborhoodsData, useObsLabelsData, useObsFeatureMatrixData, useFeatureLabelsData, useGenomicProfilesData, } from './data-hooks';
9
+ export { useHasLoader, } from './data-hook-utils';
10
+ export { AbstractLoader, AbstractTwoStepLoader, LoaderResult, } from './data/index';
11
+ export { AbstractLoaderError, DatasetNotFoundError, LoaderNotFoundError, LoaderValidationError, OptionsValidationError, DataSourceFetchError, } from './errors/index';
12
+ export {
13
+ // TODO(monorepo): should these be in here? or within file-types/
14
+ obsEmbeddingAnndataSchema, obsLocationsAnndataSchema, obsSegmentationsAnndataSchema, obsSetsAnndataSchema, obsFeatureMatrixAnndataSchema, obsLabelsAnndataSchema, featureLabelsAnndataSchema, obsEmbeddingCsvSchema, obsLocationsCsvSchema, obsLabelsCsvSchema, featureLabelsCsvSchema, obsSetsCsvSchema, anndataZarrSchema, emptySchema, } from './file-options-schemas';
15
+ export { SCHEMA_HANDLERS, LATEST_VERSION, } from './view-config-versions';
16
+ export { upgradeAndValidate, } from './view-config-utils';
17
+ export { CellColorEncodingOption, OptionsContainer, OptionSelect, usePlotOptionsStyles, } from './shared-plot-options';
18
+ export * from './schemas';