@vitessce/vit-s 3.0.0 → 3.1.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.
- package/dist/index.js +28430 -25685
- package/dist-tsc/VitS.d.ts +7 -2
- package/dist-tsc/VitS.d.ts.map +1 -1
- package/dist-tsc/VitS.js +43 -23
- package/dist-tsc/VitessceGrid.d.ts.map +1 -1
- package/dist-tsc/VitessceGrid.js +14 -11
- package/dist-tsc/VitessceGrid.test.js +5 -2
- package/dist-tsc/Warning.js +2 -2
- package/dist-tsc/data/LoaderResult.d.ts +8 -3
- package/dist-tsc/data/LoaderResult.d.ts.map +1 -1
- package/dist-tsc/data/LoaderResult.js +5 -0
- package/dist-tsc/data-hook-utils.d.ts +3 -7
- package/dist-tsc/data-hook-utils.d.ts.map +1 -1
- package/dist-tsc/data-hook-utils.js +97 -79
- package/dist-tsc/data-hooks.d.ts +12 -16
- package/dist-tsc/data-hooks.d.ts.map +1 -1
- package/dist-tsc/data-hooks.js +140 -127
- package/dist-tsc/errors/DataSourceFetchError.js +1 -1
- package/dist-tsc/hooks.d.ts +3 -7
- package/dist-tsc/hooks.d.ts.map +1 -1
- package/dist-tsc/hooks.js +12 -18
- package/dist-tsc/index.d.ts +2 -1
- package/dist-tsc/index.js +2 -1
- package/dist-tsc/mui-utils.d.ts +2 -0
- package/dist-tsc/mui-utils.d.ts.map +1 -0
- package/dist-tsc/mui-utils.js +44 -0
- package/dist-tsc/shared-plot-options/OptionSelect.js +1 -1
- package/dist-tsc/shared-plot-options/styles.js +1 -1
- package/dist-tsc/state/hooks.d.ts +27 -1
- package/dist-tsc/state/hooks.d.ts.map +1 -1
- package/dist-tsc/state/hooks.js +61 -21
- package/dist-tsc/view-config-utils.d.ts +1 -0
- package/dist-tsc/view-config-utils.d.ts.map +1 -1
- package/dist-tsc/view-config-utils.js +7 -1
- package/dist-tsc/view-config-utils.test.js +1 -0
- package/dist-tsc/vitessce-grid-layout/VitessceGridLayout.test.js +1 -1
- package/dist-tsc/vitessce-grid-layout/layout-utils.test.js +1 -0
- package/package.json +10 -9
- package/src/VitS.js +79 -43
- package/src/VitessceGrid.js +16 -10
- package/src/VitessceGrid.test.jsx +8 -2
- package/src/Warning.js +2 -2
- package/src/data/LoaderResult.js +5 -0
- package/src/data-hook-utils.js +116 -81
- package/src/data-hooks.js +148 -129
- package/src/errors/DataSourceFetchError.js +1 -1
- package/src/hooks.js +14 -21
- package/src/index.js +2 -0
- package/src/mui-utils.js +52 -0
- package/src/shared-plot-options/OptionSelect.js +1 -1
- package/src/shared-plot-options/styles.js +1 -1
- package/src/state/hooks.js +66 -21
- package/src/view-config-utils.js +8 -0
- package/src/view-config-utils.test.jsx +1 -0
- package/src/vitessce-grid-layout/VitessceGridLayout.test.jsx +1 -1
- package/src/vitessce-grid-layout/layout-utils.test.js +1 -0
- package/dist-tsc/schemas/config-0.1.0.schema.json +0 -84
- package/dist-tsc/schemas/config-1.0.0.schema.json +0 -733
- package/dist-tsc/schemas/config-1.0.1.schema.json +0 -909
- package/dist-tsc/schemas/config-1.0.10.schema.json +0 -969
- package/dist-tsc/schemas/config-1.0.11.schema.json +0 -990
- package/dist-tsc/schemas/config-1.0.12.schema.json +0 -997
- package/dist-tsc/schemas/config-1.0.13.schema.json +0 -1013
- package/dist-tsc/schemas/config-1.0.14.schema.json +0 -1048
- package/dist-tsc/schemas/config-1.0.15.schema.json +0 -1048
- package/dist-tsc/schemas/config-1.0.16.schema.json +0 -1089
- package/dist-tsc/schemas/config-1.0.2.schema.json +0 -910
- package/dist-tsc/schemas/config-1.0.3.schema.json +0 -910
- package/dist-tsc/schemas/config-1.0.4.schema.json +0 -949
- package/dist-tsc/schemas/config-1.0.5.schema.json +0 -949
- package/dist-tsc/schemas/config-1.0.6.schema.json +0 -949
- package/dist-tsc/schemas/config-1.0.7.schema.json +0 -949
- package/dist-tsc/schemas/config-1.0.8.schema.json +0 -965
- package/dist-tsc/schemas/config-1.0.9.schema.json +0 -965
- package/dist-tsc/schemas/obsSets.schema.d.ts +0 -179
- package/dist-tsc/schemas/obsSets.schema.d.ts.map +0 -1
- package/dist-tsc/schemas/obsSets.schema.js +0 -195
- package/dist-tsc/schemas/obsSetsTabular.schema.d.ts +0 -57
- package/dist-tsc/schemas/obsSetsTabular.schema.d.ts.map +0 -1
- package/dist-tsc/schemas/obsSetsTabular.schema.js +0 -38
- package/dist-tsc/schemas/raster.schema.d.ts +0 -239
- package/dist-tsc/schemas/raster.schema.d.ts.map +0 -1
- package/dist-tsc/schemas/raster.schema.js +0 -120
- package/src/schemas/config-0.1.0.schema.json +0 -85
- package/src/schemas/config-1.0.0.schema.json +0 -733
- package/src/schemas/config-1.0.1.schema.json +0 -909
- package/src/schemas/config-1.0.10.schema.json +0 -969
- package/src/schemas/config-1.0.11.schema.json +0 -990
- package/src/schemas/config-1.0.12.schema.json +0 -997
- package/src/schemas/config-1.0.13.schema.json +0 -1013
- package/src/schemas/config-1.0.14.schema.json +0 -1048
- package/src/schemas/config-1.0.15.schema.json +0 -1048
- package/src/schemas/config-1.0.16.schema.json +0 -1089
- package/src/schemas/config-1.0.2.schema.json +0 -911
- package/src/schemas/config-1.0.3.schema.json +0 -911
- package/src/schemas/config-1.0.4.schema.json +0 -949
- package/src/schemas/config-1.0.5.schema.json +0 -949
- package/src/schemas/config-1.0.6.schema.json +0 -950
- package/src/schemas/config-1.0.7.schema.json +0 -950
- package/src/schemas/config-1.0.8.schema.json +0 -966
- package/src/schemas/config-1.0.9.schema.json +0 -965
- package/src/schemas/obsSets.schema.js +0 -195
- package/src/schemas/obsSetsTabular.schema.js +0 -39
- package/src/schemas/raster.schema.js +0 -121
- package/src/schemas/schema-schema.sh +0 -34
package/src/data-hooks.js
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { useState, useEffect, useMemo } from 'react';
|
|
2
2
|
import { CoordinationType, DataType, STATUS } from '@vitessce/constants-internal';
|
|
3
3
|
import { fromEntries } from '@vitessce/utils';
|
|
4
|
-
import {
|
|
4
|
+
import { useQuery, useQueries } from '@tanstack/react-query';
|
|
5
|
+
import {
|
|
6
|
+
getMatchingLoader,
|
|
7
|
+
useMultiCoordinationValues,
|
|
8
|
+
useSetWarning,
|
|
9
|
+
} from './state/hooks.js';
|
|
5
10
|
import {
|
|
6
11
|
LoaderNotFoundError,
|
|
7
12
|
} from './errors/index.js';
|
|
@@ -48,8 +53,6 @@ export function useDescription(loaders, dataset) {
|
|
|
48
53
|
* datasets and data types to loader instances.
|
|
49
54
|
* @param {string} dataset The key for a dataset,
|
|
50
55
|
* used to identify which loader to use.
|
|
51
|
-
* @param {function} addUrl A function to call to update
|
|
52
|
-
* the URL list.
|
|
53
56
|
* @param {boolean} isRequired Should a warning be thrown if
|
|
54
57
|
* loading is unsuccessful?
|
|
55
58
|
* @param {object} coordinationSetters Object where
|
|
@@ -63,111 +66,111 @@ export function useDescription(loaders, dataset) {
|
|
|
63
66
|
* number of items in the cells object.
|
|
64
67
|
*/
|
|
65
68
|
export function useObsEmbeddingData(
|
|
66
|
-
loaders, dataset,
|
|
69
|
+
loaders, dataset, isRequired,
|
|
67
70
|
coordinationSetters, initialCoordinationValues, matchOn,
|
|
68
71
|
) {
|
|
69
72
|
return useDataType(
|
|
70
73
|
DataType.OBS_EMBEDDING,
|
|
71
|
-
loaders, dataset,
|
|
74
|
+
loaders, dataset, isRequired,
|
|
72
75
|
coordinationSetters, initialCoordinationValues, matchOn,
|
|
73
76
|
);
|
|
74
77
|
}
|
|
75
78
|
|
|
76
79
|
export function useObsLocationsData(
|
|
77
|
-
loaders, dataset,
|
|
80
|
+
loaders, dataset, isRequired,
|
|
78
81
|
coordinationSetters, initialCoordinationValues, matchOn,
|
|
79
82
|
) {
|
|
80
83
|
return useDataType(
|
|
81
84
|
DataType.OBS_LOCATIONS,
|
|
82
|
-
loaders, dataset,
|
|
85
|
+
loaders, dataset, isRequired,
|
|
83
86
|
coordinationSetters, initialCoordinationValues, matchOn,
|
|
84
87
|
);
|
|
85
88
|
}
|
|
86
89
|
|
|
87
90
|
export function useObsLabelsData(
|
|
88
|
-
loaders, dataset,
|
|
91
|
+
loaders, dataset, isRequired,
|
|
89
92
|
coordinationSetters, initialCoordinationValues, matchOn,
|
|
90
93
|
) {
|
|
91
94
|
return useDataType(
|
|
92
95
|
DataType.OBS_LABELS,
|
|
93
|
-
loaders, dataset,
|
|
96
|
+
loaders, dataset, isRequired,
|
|
94
97
|
coordinationSetters, initialCoordinationValues, matchOn,
|
|
95
98
|
);
|
|
96
99
|
}
|
|
97
100
|
|
|
98
101
|
export function useObsSegmentationsData(
|
|
99
|
-
loaders, dataset,
|
|
102
|
+
loaders, dataset, isRequired,
|
|
100
103
|
coordinationSetters, initialCoordinationValues, matchOn,
|
|
101
104
|
) {
|
|
102
105
|
return useDataType(
|
|
103
106
|
DataType.OBS_SEGMENTATIONS,
|
|
104
|
-
loaders, dataset,
|
|
107
|
+
loaders, dataset, isRequired,
|
|
105
108
|
coordinationSetters, initialCoordinationValues, matchOn,
|
|
106
109
|
);
|
|
107
110
|
}
|
|
108
111
|
|
|
109
112
|
export function useObsSetsData(
|
|
110
|
-
loaders, dataset,
|
|
113
|
+
loaders, dataset, isRequired,
|
|
111
114
|
coordinationSetters, initialCoordinationValues, matchOn,
|
|
112
115
|
) {
|
|
113
116
|
return useDataType(
|
|
114
117
|
DataType.OBS_SETS,
|
|
115
|
-
loaders, dataset,
|
|
118
|
+
loaders, dataset, isRequired,
|
|
116
119
|
coordinationSetters, initialCoordinationValues, matchOn,
|
|
117
120
|
);
|
|
118
121
|
}
|
|
119
122
|
|
|
120
123
|
export function useObsFeatureMatrixData(
|
|
121
|
-
loaders, dataset,
|
|
124
|
+
loaders, dataset, isRequired,
|
|
122
125
|
coordinationSetters, initialCoordinationValues, matchOn,
|
|
123
126
|
) {
|
|
124
127
|
return useDataType(
|
|
125
128
|
DataType.OBS_FEATURE_MATRIX,
|
|
126
|
-
loaders, dataset,
|
|
129
|
+
loaders, dataset, isRequired,
|
|
127
130
|
coordinationSetters, initialCoordinationValues, matchOn,
|
|
128
131
|
);
|
|
129
132
|
}
|
|
130
133
|
|
|
131
134
|
export function useFeatureLabelsData(
|
|
132
|
-
loaders, dataset,
|
|
135
|
+
loaders, dataset, isRequired,
|
|
133
136
|
coordinationSetters, initialCoordinationValues, matchOn,
|
|
134
137
|
) {
|
|
135
138
|
return useDataType(
|
|
136
139
|
DataType.FEATURE_LABELS,
|
|
137
|
-
loaders, dataset,
|
|
140
|
+
loaders, dataset, isRequired,
|
|
138
141
|
coordinationSetters, initialCoordinationValues, matchOn,
|
|
139
142
|
);
|
|
140
143
|
}
|
|
141
144
|
|
|
142
145
|
export function useImageData(
|
|
143
|
-
loaders, dataset,
|
|
146
|
+
loaders, dataset, isRequired,
|
|
144
147
|
coordinationSetters, initialCoordinationValues, matchOn,
|
|
145
148
|
) {
|
|
146
149
|
return useDataType(
|
|
147
150
|
DataType.IMAGE,
|
|
148
|
-
loaders, dataset,
|
|
151
|
+
loaders, dataset, isRequired,
|
|
149
152
|
coordinationSetters, initialCoordinationValues, matchOn,
|
|
150
153
|
);
|
|
151
154
|
}
|
|
152
155
|
|
|
153
156
|
export function useGenomicProfilesData(
|
|
154
|
-
loaders, dataset,
|
|
157
|
+
loaders, dataset, isRequired,
|
|
155
158
|
coordinationSetters, initialCoordinationValues, matchOn,
|
|
156
159
|
) {
|
|
157
160
|
return useDataType(
|
|
158
161
|
DataType.GENOMIC_PROFILES,
|
|
159
|
-
loaders, dataset,
|
|
162
|
+
loaders, dataset, isRequired,
|
|
160
163
|
coordinationSetters, initialCoordinationValues, matchOn,
|
|
161
164
|
);
|
|
162
165
|
}
|
|
163
166
|
|
|
164
167
|
export function useNeighborhoodsData(
|
|
165
|
-
loaders, dataset,
|
|
168
|
+
loaders, dataset, isRequired,
|
|
166
169
|
coordinationSetters, initialCoordinationValues, matchOn,
|
|
167
170
|
) {
|
|
168
171
|
return useDataType(
|
|
169
172
|
DataType.NEIGHBORHOODS,
|
|
170
|
-
loaders, dataset,
|
|
173
|
+
loaders, dataset, isRequired,
|
|
171
174
|
coordinationSetters, initialCoordinationValues, matchOn,
|
|
172
175
|
);
|
|
173
176
|
}
|
|
@@ -193,73 +196,71 @@ export function useFeatureSelection(
|
|
|
193
196
|
selection,
|
|
194
197
|
matchOn,
|
|
195
198
|
) {
|
|
196
|
-
const [geneData, setGeneData] = useState();
|
|
197
|
-
const [status, setStatus] = useState(STATUS.LOADING);
|
|
198
|
-
const [loadedGeneName, setLoadedGeneName] = useState(null);
|
|
199
|
-
|
|
200
199
|
const setWarning = useSetWarning();
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
.loadGeneSelection({ selection })
|
|
218
|
-
.catch(e => warn(e, setWarning))
|
|
219
|
-
.then((payload) => {
|
|
220
|
-
if (!payload) return;
|
|
200
|
+
const featureQueries = useQueries({
|
|
201
|
+
queries: selection?.map(featureId => ({
|
|
202
|
+
structuralSharing: false,
|
|
203
|
+
placeholderData: null,
|
|
204
|
+
queryKey: [dataset, DataType.OBS_FEATURE_MATRIX, matchOn, featureId, 'useFeatureSelection'],
|
|
205
|
+
// Query function should return an object
|
|
206
|
+
// { data, dataKey } where dataKey is the loaded gene selection.
|
|
207
|
+
queryFn: async (ctx) => {
|
|
208
|
+
const loader = getMatchingLoader(
|
|
209
|
+
ctx.meta.loaders, ctx.queryKey[0], ctx.queryKey[1], ctx.queryKey[2],
|
|
210
|
+
);
|
|
211
|
+
if (loader) {
|
|
212
|
+
const implementsGeneSelection = typeof loader.loadGeneSelection === 'function';
|
|
213
|
+
if (implementsGeneSelection) {
|
|
214
|
+
const payload = await loader.loadGeneSelection({ selection: [featureId] });
|
|
215
|
+
if (!payload) return null;
|
|
221
216
|
const { data } = payload;
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
loader.load().catch(e => warn(e, setWarning)).then((payload) => {
|
|
228
|
-
if (!payload) return;
|
|
217
|
+
return { data: data[0], dataKey: selection };
|
|
218
|
+
}
|
|
219
|
+
// Loader does not implement loadGeneSelection.
|
|
220
|
+
const payload = await loader.load();
|
|
221
|
+
if (!payload) return null;
|
|
229
222
|
const { data } = payload;
|
|
230
223
|
const { obsIndex, featureIndex, obsFeatureMatrix } = data;
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
224
|
+
// Compute expressionData
|
|
225
|
+
const geneIndex = featureIndex.indexOf(featureId);
|
|
226
|
+
const numGenes = featureIndex.length;
|
|
227
|
+
const numCells = obsIndex.length;
|
|
228
|
+
const expressionData = new Float32Array(numCells);
|
|
229
|
+
for (let cellIndex = 0; cellIndex < numCells; cellIndex += 1) {
|
|
230
|
+
expressionData[cellIndex] = obsFeatureMatrix.data[cellIndex * numGenes + geneIndex];
|
|
231
|
+
}
|
|
232
|
+
return { data: expressionData, dataKey: featureId };
|
|
233
|
+
}
|
|
234
|
+
// No loader was found.
|
|
235
|
+
if (isRequired) {
|
|
236
|
+
throw new LoaderNotFoundError(loaders, dataset, DataType.OBS_FEATURE_MATRIX, matchOn);
|
|
237
|
+
} else {
|
|
238
|
+
return { data: null, dataKey: null };
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
meta: { loaders },
|
|
242
|
+
})) || [],
|
|
243
|
+
});
|
|
244
|
+
const anyLoading = featureQueries.some(q => q.isFetching);
|
|
245
|
+
const anyError = featureQueries.some(q => q.isError);
|
|
246
|
+
// eslint-disable-next-line no-nested-ternary
|
|
247
|
+
const dataStatus = anyLoading ? STATUS.LOADING : (anyError ? STATUS.ERROR : STATUS.SUCCESS);
|
|
248
|
+
const isSuccess = dataStatus === STATUS.SUCCESS;
|
|
249
|
+
const geneData = isSuccess ? featureQueries.map(q => q.data?.data || null) : null;
|
|
250
|
+
const loadedGeneName = isSuccess ? featureQueries.map(q => q.data?.dataKey || null) : null;
|
|
251
|
+
|
|
252
|
+
useEffect(() => {
|
|
253
|
+
featureQueries
|
|
254
|
+
.map(q => q.error)
|
|
255
|
+
.filter(e => Boolean(e))
|
|
256
|
+
.forEach((error) => {
|
|
257
|
+
warn(error, setWarning);
|
|
258
|
+
});
|
|
259
|
+
// Deliberate dependency omissions: use indirect dependencies for efficiency.
|
|
259
260
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
260
|
-
}, [
|
|
261
|
+
}, [anyError, setWarning]);
|
|
261
262
|
|
|
262
|
-
return [geneData, loadedGeneName,
|
|
263
|
+
return [geneData, loadedGeneName, dataStatus];
|
|
263
264
|
}
|
|
264
265
|
|
|
265
266
|
/**
|
|
@@ -272,68 +273,85 @@ export function useFeatureSelection(
|
|
|
272
273
|
* datasets and data types to loader instances.
|
|
273
274
|
* @param {string} dataset The key for a dataset,
|
|
274
275
|
* used to identify which loader to use.
|
|
275
|
-
* @param {function} addUrl A function to call to update
|
|
276
|
-
* the URL list.
|
|
277
276
|
* @param {boolean} isRequired Should a warning be thrown if
|
|
278
277
|
* loading is unsuccessful?
|
|
279
278
|
* @returns {object} [attrs] { rows, cols } object containing cell and gene names.
|
|
280
279
|
*/
|
|
281
280
|
export function useObsFeatureMatrixIndices(
|
|
282
|
-
loaders, dataset,
|
|
281
|
+
loaders, dataset, isRequired, matchOn,
|
|
283
282
|
) {
|
|
284
|
-
const [data, setData] = useState({});
|
|
285
|
-
const [status, setStatus] = useState(STATUS.LOADING);
|
|
286
|
-
|
|
287
283
|
const setWarning = useSetWarning();
|
|
288
|
-
const
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
284
|
+
const placeholderObject = useMemo(() => ({}), []);
|
|
285
|
+
const indicesQuery = useQuery({
|
|
286
|
+
// TODO: only enable once `loaders` is available?
|
|
287
|
+
structuralSharing: false,
|
|
288
|
+
placeholderData: placeholderObject,
|
|
289
|
+
// Include the hook name in the queryKey to prevent the case in which an identical queryKey
|
|
290
|
+
// in a different hook would cause an accidental cache hit.
|
|
291
|
+
queryKey: [dataset, DataType.OBS_FEATURE_MATRIX, matchOn, 'useObsFeatureMatrixIndices'],
|
|
292
|
+
// Query function should return an object
|
|
293
|
+
// { data, dataKey } where dataKey is the loaded gene selection.
|
|
294
|
+
// TODO: use TypeScript to type the return value?
|
|
295
|
+
queryFn: async (ctx) => {
|
|
296
|
+
const loader = getMatchingLoader(
|
|
297
|
+
ctx.meta.loaders, ctx.queryKey[0], ctx.queryKey[1], ctx.queryKey[2],
|
|
298
|
+
);
|
|
299
|
+
if (loader) {
|
|
300
|
+
const implementsLoadAttrs = typeof loader.loadAttrs === 'function';
|
|
301
|
+
if (implementsLoadAttrs) {
|
|
302
|
+
// Has loadAttrs function.
|
|
303
|
+
const payload = await loader.loadAttrs();
|
|
304
|
+
if (!payload) return placeholderObject;
|
|
308
305
|
const { data: payloadData, url } = payload;
|
|
309
|
-
|
|
306
|
+
|
|
307
|
+
return {
|
|
308
|
+
data: {
|
|
309
|
+
obsIndex: payloadData.rows,
|
|
310
|
+
featureIndex: payloadData.cols,
|
|
311
|
+
},
|
|
312
|
+
urls: [{ url, name: DataType.OBS_FEATURE_MATRIX }],
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
// No loadAttrs function.
|
|
316
|
+
const payload = await loader.load();
|
|
317
|
+
if (!payload) return placeholderObject;
|
|
318
|
+
const { data: payloadData, url } = payload;
|
|
319
|
+
return {
|
|
320
|
+
data: {
|
|
310
321
|
obsIndex: payloadData.obsIndex,
|
|
311
322
|
featureIndex: payloadData.featureIndex,
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
});
|
|
323
|
+
},
|
|
324
|
+
urls: [{ url, name: DataType.OBS_FEATURE_MATRIX }],
|
|
325
|
+
};
|
|
316
326
|
}
|
|
317
|
-
|
|
318
|
-
setData({});
|
|
327
|
+
// No loader was found.
|
|
319
328
|
if (isRequired) {
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
setWarning,
|
|
323
|
-
);
|
|
324
|
-
setStatus(STATUS.ERROR);
|
|
329
|
+
// Status: error
|
|
330
|
+
throw new LoaderNotFoundError(loaders, dataset, DataType.OBS_FEATURE_MATRIX, matchOn);
|
|
325
331
|
} else {
|
|
326
|
-
|
|
332
|
+
// Status: success
|
|
333
|
+
return { data: placeholderObject, dataKey: null };
|
|
327
334
|
}
|
|
335
|
+
},
|
|
336
|
+
meta: { loaders },
|
|
337
|
+
});
|
|
338
|
+
const { data, status, isFetching, error } = indicesQuery;
|
|
339
|
+
const loadedData = data?.data || placeholderObject;
|
|
340
|
+
|
|
341
|
+
const dataStatus = isFetching ? STATUS.LOADING : status;
|
|
342
|
+
const urls = data?.urls;
|
|
343
|
+
|
|
344
|
+
useEffect(() => {
|
|
345
|
+
if (error) {
|
|
346
|
+
setWarning(error.message);
|
|
328
347
|
}
|
|
329
|
-
|
|
330
|
-
}, [loader]);
|
|
348
|
+
}, [error, setWarning]);
|
|
331
349
|
|
|
332
|
-
return [
|
|
350
|
+
return [loadedData, dataStatus, urls];
|
|
333
351
|
}
|
|
334
352
|
|
|
335
353
|
export function useMultiObsLabels(
|
|
336
|
-
coordinationScopes, obsType, loaders, dataset,
|
|
354
|
+
coordinationScopes, obsType, loaders, dataset,
|
|
337
355
|
) {
|
|
338
356
|
const obsLabelsTypes = useMultiCoordinationValues(
|
|
339
357
|
CoordinationType.OBS_LABELS_TYPE,
|
|
@@ -347,8 +365,9 @@ export function useMultiObsLabels(
|
|
|
347
365
|
), [obsLabelsTypes, obsType]);
|
|
348
366
|
const [obsLabelsData, obsLabelsDataStatus] = useDataTypeMulti(
|
|
349
367
|
DataType.OBS_LABELS, loaders, dataset,
|
|
350
|
-
|
|
368
|
+
false, {}, {},
|
|
351
369
|
obsLabelsMatchOnObj,
|
|
352
370
|
);
|
|
353
|
-
|
|
371
|
+
const urls = null; // TODO?
|
|
372
|
+
return [obsLabelsTypes, obsLabelsData, obsLabelsDataStatus, urls];
|
|
354
373
|
}
|
|
@@ -10,6 +10,6 @@ export default class DataSourceFetchError extends AbstractLoaderError {
|
|
|
10
10
|
|
|
11
11
|
warnInConsole() {
|
|
12
12
|
const { source, url, headers } = this;
|
|
13
|
-
console.warn(`${source} failed to fetch from ${url} with headers ${headers}`);
|
|
13
|
+
console.warn(`${source} failed to fetch from ${url} with headers ${JSON.stringify(headers)}`);
|
|
14
14
|
}
|
|
15
15
|
}
|
package/src/hooks.js
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
import { debounce, every } from 'lodash-es';
|
|
5
5
|
import { extent } from 'd3-array';
|
|
6
6
|
import { capitalize, fromEntries } from '@vitessce/utils';
|
|
7
|
+
import { STATUS } from '@vitessce/constants-internal';
|
|
7
8
|
import { useGridResize, useEmitGridResize } from './state/hooks.js';
|
|
8
9
|
import { VITESSCE_CONTAINER } from './classNames.js';
|
|
9
10
|
|
|
@@ -137,34 +138,26 @@ export function useDeckCanvasSize() {
|
|
|
137
138
|
*/
|
|
138
139
|
export function useReady(statusValues) {
|
|
139
140
|
return useMemo(() => every(
|
|
140
|
-
statusValues, val => val
|
|
141
|
+
statusValues, val => val !== STATUS.LOADING,
|
|
141
142
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
142
143
|
), statusValues);
|
|
143
144
|
}
|
|
144
145
|
|
|
145
146
|
/**
|
|
146
147
|
* This hook helps manage a list of URLs.
|
|
147
|
-
* @param {object}
|
|
148
|
-
* @
|
|
149
|
-
* @returns {array} An array
|
|
150
|
-
* [urls, addUrl]
|
|
151
|
-
* where urls is the array of URL objects,
|
|
152
|
-
* and addUrl is a function for adding a URL to the array.
|
|
148
|
+
* @param {(null|object[])[]} urls Array of (null or array of { url, name }).
|
|
149
|
+
* @returns {array} An array of { url, name } objects (flattened from the input).
|
|
153
150
|
*/
|
|
154
|
-
export function useUrls(
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
setUrls([]);
|
|
165
|
-
}, [loaders, dataset]);
|
|
166
|
-
|
|
167
|
-
return [urls, addUrl];
|
|
151
|
+
export function useUrls(urls) {
|
|
152
|
+
const mergedUrls = useMemo(
|
|
153
|
+
() => urls.filter(a => Array.isArray(a)).flat().filter((url, index, array) => {
|
|
154
|
+
const firstIndex = array.findIndex(u => u.name === url.name);
|
|
155
|
+
return index === firstIndex;
|
|
156
|
+
}),
|
|
157
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
158
|
+
urls,
|
|
159
|
+
);
|
|
160
|
+
return mergedUrls;
|
|
168
161
|
}
|
|
169
162
|
|
|
170
163
|
/**
|
package/src/index.js
CHANGED
|
@@ -17,6 +17,7 @@ export {
|
|
|
17
17
|
useGridItemSize,
|
|
18
18
|
} from './hooks.js';
|
|
19
19
|
export {
|
|
20
|
+
useInitialCoordination,
|
|
20
21
|
useCoordination,
|
|
21
22
|
useComplexCoordination,
|
|
22
23
|
useMultiCoordinationValues,
|
|
@@ -74,3 +75,4 @@ export {
|
|
|
74
75
|
OptionSelect,
|
|
75
76
|
usePlotOptionsStyles,
|
|
76
77
|
} from './shared-plot-options/index.js';
|
|
78
|
+
export { logConfig } from './view-config-utils.js';
|
package/src/mui-utils.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// This function has been copied from MUI v4
|
|
2
|
+
// with logic related to randomness / random numbers removed.
|
|
3
|
+
// Reference: https://github.com/mui/material-ui/blob/0adada09/packages/mui-styles/src/createGenerateClassName/createGenerateClassName.js#L29
|
|
4
|
+
/**
|
|
5
|
+
* This is the list of the style rule name we use as drop in replacement for the built-in
|
|
6
|
+
* pseudo classes (:checked, :disabled, :focused, etc.).
|
|
7
|
+
*
|
|
8
|
+
* Why do they exist in the first place?
|
|
9
|
+
* These classes are used at a specificity of 2.
|
|
10
|
+
* It allows them to override previously defined styles as well as
|
|
11
|
+
* being untouched by simple user overrides.
|
|
12
|
+
*/
|
|
13
|
+
const stateClasses = [
|
|
14
|
+
'checked',
|
|
15
|
+
'disabled',
|
|
16
|
+
'error',
|
|
17
|
+
'focused',
|
|
18
|
+
'focusVisible',
|
|
19
|
+
'required',
|
|
20
|
+
'expanded',
|
|
21
|
+
'selected',
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
const defaultPrefix = 'vit-';
|
|
25
|
+
|
|
26
|
+
export function createGenerateClassName(customPrefix) {
|
|
27
|
+
return (rule, styleSheet) => {
|
|
28
|
+
const {
|
|
29
|
+
name: styleSheetName,
|
|
30
|
+
link: styleSheetLink,
|
|
31
|
+
classNamePrefix,
|
|
32
|
+
} = styleSheet.options;
|
|
33
|
+
const { key: ruleKey } = rule;
|
|
34
|
+
|
|
35
|
+
const seedPrefix = customPrefix ? `${customPrefix}-` : defaultPrefix;
|
|
36
|
+
|
|
37
|
+
// Is a global static MUI style?
|
|
38
|
+
if (styleSheetName && styleSheetName.indexOf('Mui') === 0 && !styleSheetLink) {
|
|
39
|
+
// We can use a shorthand class name, we never use the keys to style the components.
|
|
40
|
+
if (stateClasses.indexOf(ruleKey) !== -1) {
|
|
41
|
+
return `Mui-${ruleKey}`;
|
|
42
|
+
}
|
|
43
|
+
const prefix = `${seedPrefix}${styleSheetName}-${ruleKey}`;
|
|
44
|
+
return prefix;
|
|
45
|
+
}
|
|
46
|
+
// Help with debuggability.
|
|
47
|
+
if (classNamePrefix) {
|
|
48
|
+
return `${seedPrefix}${classNamePrefix}-${ruleKey}`;
|
|
49
|
+
}
|
|
50
|
+
return `${seedPrefix}${ruleKey}`;
|
|
51
|
+
};
|
|
52
|
+
}
|