@vitessce/vit-s 2.0.2 → 2.0.3
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.mjs +84801 -0
- package/{dist → dist-tsc}/index.js +2 -2
- package/package.json +7 -7
- package/src/CallbackPublisher.js +81 -0
- package/src/LoadingIndicator.js +34 -0
- package/src/TitleInfo.js +240 -0
- package/src/VitS.js +180 -0
- package/src/VitessceGrid.js +110 -0
- package/src/VitessceGrid.test.jsx +48 -0
- package/src/Warning.js +62 -0
- package/{dist → src}/classNames.js +0 -0
- package/src/component-registry.js +21 -0
- package/src/data/AbstractLoader.js +46 -0
- package/{dist → src}/data/AbstractTwoStepLoader.js +5 -4
- package/src/data/LoaderResult.js +8 -0
- package/{dist → src}/data/index.js +0 -0
- package/src/data/loader-registry.js +19 -0
- package/src/data-hook-utils.js +197 -0
- package/src/data-hooks.js +354 -0
- package/src/errors/AbstractLoaderError.js +14 -0
- package/src/errors/DataSourceFetchError.js +15 -0
- package/src/errors/DatasetNotFoundError.js +23 -0
- package/src/errors/LoaderNotFoundError.js +24 -0
- package/src/errors/LoaderValidationError.js +23 -0
- package/src/errors/OptionsValidationError.js +25 -0
- package/{dist → src}/errors/index.js +0 -0
- package/src/file-options-schemas-legacy.js +139 -0
- package/src/file-options-schemas-legacy.test.js +138 -0
- package/src/file-options-schemas.js +327 -0
- package/src/file-options-schemas.test.js +26 -0
- package/src/hooks.js +252 -0
- package/src/index.js +101 -0
- package/src/joint-file-types-legacy.js +298 -0
- package/src/joint-file-types-legacy.test.js +412 -0
- package/src/joint-file-types.js +171 -0
- package/src/joint-file-types.test.js +144 -0
- package/{dist/schemas.js → src/json-schemas.js} +6 -1
- package/{dist → src}/plugins.js +102 -70
- package/src/plugins.test.fixtures.js +78 -0
- package/src/plugins.test.js +42 -0
- package/src/schemas/config-0.1.0.schema.json +85 -0
- package/src/schemas/config-1.0.0.schema.json +733 -0
- package/src/schemas/config-1.0.1.schema.json +909 -0
- package/src/schemas/config-1.0.10.schema.json +969 -0
- package/src/schemas/config-1.0.11.schema.json +990 -0
- package/src/schemas/config-1.0.12.schema.json +997 -0
- package/src/schemas/config-1.0.13.schema.json +1013 -0
- package/src/schemas/config-1.0.14.schema.json +1048 -0
- package/src/schemas/config-1.0.15.schema.json +1048 -0
- package/src/schemas/config-1.0.16.schema.json +1069 -0
- package/src/schemas/config-1.0.16.schema.test.js +32 -0
- package/src/schemas/config-1.0.2.schema.json +911 -0
- package/src/schemas/config-1.0.3.schema.json +911 -0
- package/src/schemas/config-1.0.4.schema.json +949 -0
- package/src/schemas/config-1.0.5.schema.json +949 -0
- package/src/schemas/config-1.0.6.schema.json +950 -0
- package/src/schemas/config-1.0.7.schema.json +950 -0
- package/src/schemas/config-1.0.8.schema.json +966 -0
- package/src/schemas/config-1.0.9.schema.json +965 -0
- package/src/schemas/fixtures/cellSets.good.json +16 -0
- package/src/schemas/fixtures/config-1.0.1.bad.json +1 -0
- package/src/schemas/fixtures/config-1.0.1.bad.message.json +11 -0
- package/src/schemas/fixtures/config-1.0.1.good.json +37 -0
- package/src/schemas/fixtures/config-1.0.2.bad.json +1 -0
- package/src/schemas/fixtures/config-1.0.2.bad.message.json +11 -0
- package/src/schemas/fixtures/config-1.0.2.good.json +38 -0
- package/src/schemas/fixtures/config-1.0.3.bad.json +1 -0
- package/src/schemas/fixtures/config-1.0.3.bad.message.json +11 -0
- package/src/schemas/fixtures/config-1.0.3.good.json +38 -0
- package/src/schemas/fixtures/obsSets.bad.json +1 -0
- package/src/schemas/fixtures/obsSets.bad.message.json +11 -0
- package/src/schemas/fixtures/obsSets.good.json +16 -0
- package/src/schemas/fixtures/obsSetsTabular.bad.json +1 -0
- package/src/schemas/fixtures/obsSetsTabular.bad.message.json +11 -0
- package/src/schemas/fixtures/obsSetsTabular.good.json +26 -0
- package/src/schemas/fixtures/raster.bad.json +1 -0
- package/src/schemas/fixtures/raster.bad.message.json +11 -0
- package/src/schemas/fixtures/raster.good.json +39 -0
- package/src/schemas/obsSets.schema.js +195 -0
- package/src/schemas/obsSetsTabular.schema.js +39 -0
- package/src/schemas/raster.schema.js +121 -0
- package/src/schemas/schema-schema.sh +34 -0
- package/{dist → src}/schemas/schema.test-old.js +0 -1
- package/src/shared-mui/components.js +79 -0
- package/src/shared-mui/container.js +212 -0
- package/src/shared-mui/styles.js +110 -0
- package/src/shared-plot-options/CellColorEncodingOption.js +43 -0
- package/src/shared-plot-options/OptionSelect.js +19 -0
- package/src/shared-plot-options/OptionsContainer.js +26 -0
- package/{dist → src}/shared-plot-options/index.js +0 -0
- package/src/shared-plot-options/styles.js +49 -0
- package/src/state/hooks.js +633 -0
- package/src/view-config-upgraders.js +628 -0
- package/src/view-config-utils.js +315 -0
- package/src/view-config-utils.test.fixtures.js +893 -0
- package/src/view-config-utils.test.js +95 -0
- package/src/view-config-versions.js +68 -0
- package/src/vitessce-grid-layout/VitessceGridLayout.js +158 -0
- package/src/vitessce-grid-layout/VitessceGridLayout.test.jsx +56 -0
- package/{dist → src}/vitessce-grid-layout/index.js +0 -0
- package/src/vitessce-grid-layout/layout-utils.js +76 -0
- package/src/vitessce-grid-layout/layout-utils.test.js +167 -0
- package/src/vitessce-grid-utils.js +160 -0
- package/dist/CallbackPublisher.js +0 -68
- package/dist/LoadingIndicator.js +0 -27
- package/dist/TitleInfo.js +0 -151
- package/dist/VitS.js +0 -112
- package/dist/VitessceGrid.js +0 -59
- package/dist/VitessceGrid.test.js +0 -36
- package/dist/Warning.js +0 -45
- package/dist/component-registry.js +0 -16
- package/dist/data/AbstractLoader.js +0 -35
- package/dist/data/LoaderResult.js +0 -7
- package/dist/data/loader-registry.js +0 -15
- package/dist/data-hook-utils.js +0 -175
- package/dist/data-hooks.js +0 -241
- package/dist/errors/AbstractLoaderError.js +0 -13
- package/dist/errors/DataSourceFetchError.js +0 -13
- package/dist/errors/DatasetNotFoundError.js +0 -17
- package/dist/errors/LoaderNotFoundError.js +0 -17
- package/dist/errors/LoaderValidationError.js +0 -15
- package/dist/errors/OptionsValidationError.js +0 -15
- package/dist/file-options-schemas-legacy.js +0 -136
- package/dist/file-options-schemas-legacy.test.js +0 -126
- package/dist/file-options-schemas.js +0 -322
- package/dist/file-options-schemas.test.js +0 -23
- package/dist/hooks.js +0 -215
- package/dist/joint-file-types-legacy.js +0 -278
- package/dist/joint-file-types-legacy.test.js +0 -400
- package/dist/joint-file-types.js +0 -148
- package/dist/joint-file-types.test.js +0 -139
- package/dist/plugins.test.fixtures.js +0 -76
- package/dist/plugins.test.js +0 -30
- package/dist/schemas/config-0.1.0.schema.json +0 -84
- package/dist/schemas/config-1.0.0.schema.json +0 -733
- package/dist/schemas/config-1.0.1.schema.json +0 -909
- package/dist/schemas/config-1.0.10.schema.json +0 -969
- package/dist/schemas/config-1.0.11.schema.json +0 -990
- package/dist/schemas/config-1.0.12.schema.json +0 -997
- package/dist/schemas/config-1.0.13.schema.json +0 -1013
- package/dist/schemas/config-1.0.14.schema.json +0 -1048
- package/dist/schemas/config-1.0.15.schema.json +0 -1048
- package/dist/schemas/config-1.0.15.schema.test.js +0 -22
- package/dist/schemas/config-1.0.2.schema.json +0 -910
- package/dist/schemas/config-1.0.3.schema.json +0 -910
- package/dist/schemas/config-1.0.4.schema.json +0 -949
- package/dist/schemas/config-1.0.5.schema.json +0 -949
- package/dist/schemas/config-1.0.6.schema.json +0 -949
- package/dist/schemas/config-1.0.7.schema.json +0 -949
- package/dist/schemas/config-1.0.8.schema.json +0 -965
- package/dist/schemas/config-1.0.9.schema.json +0 -965
- package/dist/schemas/obsSets.schema.js +0 -195
- package/dist/schemas/obsSetsTabular.schema.js +0 -38
- package/dist/schemas/raster.schema.js +0 -120
- package/dist/shared-mui/components.js +0 -35
- package/dist/shared-mui/container.js +0 -211
- package/dist/shared-mui/styles.js +0 -73
- package/dist/shared-plot-options/CellColorEncodingOption.js +0 -18
- package/dist/shared-plot-options/OptionSelect.js +0 -12
- package/dist/shared-plot-options/OptionsContainer.js +0 -12
- package/dist/shared-plot-options/styles.js +0 -48
- package/dist/state/hooks.js +0 -549
- package/dist/view-config-upgraders.js +0 -525
- package/dist/view-config-utils.js +0 -286
- package/dist/view-config-utils.test.fixtures.js +0 -765
- package/dist/view-config-utils.test.js +0 -66
- package/dist/view-config-versions.js +0 -47
- package/dist/vitessce-grid-layout/VitessceGridLayout.js +0 -95
- package/dist/vitessce-grid-layout/VitessceGridLayout.test.js +0 -40
- package/dist/vitessce-grid-layout/layout-utils.js +0 -60
- package/dist/vitessce-grid-layout/layout-utils.test.js +0 -146
- package/dist/vitessce-grid-utils.js +0 -140
|
@@ -0,0 +1,628 @@
|
|
|
1
|
+
/* eslint-disable camelcase */
|
|
2
|
+
import uuidv4 from 'uuid/v4';
|
|
3
|
+
import cloneDeep from 'lodash/cloneDeep';
|
|
4
|
+
import { getNextScope, capitalize } from '@vitessce/utils';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A helper function for the `upgrade()` function,
|
|
8
|
+
* which helps convert `props.view` (for scatterplot and spatial),
|
|
9
|
+
* into new coordination scopes, setting their values
|
|
10
|
+
* in the coordination space and returning the new scope mappings.
|
|
11
|
+
* This function does mutate the `coordinationSpace` parameter.
|
|
12
|
+
* @param {string} prefix The coordination type prefix,
|
|
13
|
+
* either 'embedding' or 'spatial'.
|
|
14
|
+
* @param {object} view The view prop object containing
|
|
15
|
+
* the properties `.target` and `.zoom`.
|
|
16
|
+
* @param {object} coordinationSpace The coordination space.
|
|
17
|
+
* @returns {object} The new coordination scope names.
|
|
18
|
+
*/
|
|
19
|
+
function upgradeReplaceViewProp(prefix, view, coordinationSpace) {
|
|
20
|
+
const prevZScopes = Object.keys(coordinationSpace[`${prefix}Zoom`]);
|
|
21
|
+
const prevTXScopes = Object.keys(coordinationSpace[`${prefix}TargetX`]);
|
|
22
|
+
const prevTYScopes = Object.keys(coordinationSpace[`${prefix}TargetY`]);
|
|
23
|
+
|
|
24
|
+
const nextZScope = getNextScope(prevZScopes);
|
|
25
|
+
const nextTXScope = getNextScope(prevTXScopes);
|
|
26
|
+
const nextTYScope = getNextScope(prevTYScopes);
|
|
27
|
+
|
|
28
|
+
const { zoom, target: [targetX, targetY] } = view;
|
|
29
|
+
// eslint-disable-next-line no-param-reassign
|
|
30
|
+
coordinationSpace[`${prefix}Zoom`][nextZScope] = zoom;
|
|
31
|
+
// eslint-disable-next-line no-param-reassign
|
|
32
|
+
coordinationSpace[`${prefix}TargetX`][nextTXScope] = targetX;
|
|
33
|
+
// eslint-disable-next-line no-param-reassign
|
|
34
|
+
coordinationSpace[`${prefix}TargetY`][nextTYScope] = targetY;
|
|
35
|
+
return {
|
|
36
|
+
[`${prefix}Zoom`]: nextZScope,
|
|
37
|
+
[`${prefix}TargetX`]: nextTXScope,
|
|
38
|
+
[`${prefix}TargetY`]: nextTYScope,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Convert an older view config to a newer view config.
|
|
44
|
+
* @param {object} config A v0.1.0 "legacy" view config.
|
|
45
|
+
* @returns {object} A v1.0.0 "upgraded" view config.
|
|
46
|
+
*/
|
|
47
|
+
export function upgradeFrom0_1_0(config, datasetUid = null) {
|
|
48
|
+
const coordinationSpace = {
|
|
49
|
+
embeddingType: {},
|
|
50
|
+
embeddingZoom: {},
|
|
51
|
+
embeddingTargetX: {},
|
|
52
|
+
embeddingTargetY: {},
|
|
53
|
+
spatialZoom: {},
|
|
54
|
+
spatialTargetX: {},
|
|
55
|
+
spatialTargetY: {},
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const layout = [];
|
|
59
|
+
config.staticLayout.forEach((componentDef) => {
|
|
60
|
+
let newComponentDef = {
|
|
61
|
+
...componentDef,
|
|
62
|
+
coordinationScopes: {},
|
|
63
|
+
};
|
|
64
|
+
if (componentDef.component === 'scatterplot') {
|
|
65
|
+
// Need to set up the coordinationSpace
|
|
66
|
+
// with embeddingType to replace scatterplot
|
|
67
|
+
// component prop "mapping".
|
|
68
|
+
if (componentDef.props.mapping) {
|
|
69
|
+
coordinationSpace.embeddingType[componentDef.props.mapping] = componentDef.props.mapping;
|
|
70
|
+
newComponentDef = {
|
|
71
|
+
...newComponentDef,
|
|
72
|
+
coordinationScopes: {
|
|
73
|
+
...newComponentDef.coordinationScopes,
|
|
74
|
+
embeddingType: componentDef.props.mapping,
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
// Need to set up the coordinationSpace
|
|
79
|
+
// with embeddingZoom / embeddingTargetX/Y to replace scatterplot
|
|
80
|
+
// component prop "view" ({ zoom, target }).
|
|
81
|
+
if (componentDef.props.view) {
|
|
82
|
+
// Note that the below function does mutate the coordinationSpace param.
|
|
83
|
+
const newScopeValues = upgradeReplaceViewProp(
|
|
84
|
+
'embedding', componentDef.props.view, coordinationSpace,
|
|
85
|
+
);
|
|
86
|
+
newComponentDef = {
|
|
87
|
+
...newComponentDef,
|
|
88
|
+
coordinationScopes: {
|
|
89
|
+
...newComponentDef.coordinationScopes,
|
|
90
|
+
...newScopeValues,
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (componentDef.component === 'spatial') {
|
|
96
|
+
// Need to set up the coordinationSpace
|
|
97
|
+
// with spatialZoom / spatialTargetX/Y to replace spatial
|
|
98
|
+
// component prop "view" ({ zoom, target }).
|
|
99
|
+
if (componentDef?.props?.view) {
|
|
100
|
+
// Note that the below function does mutate the coordinationSpace param.
|
|
101
|
+
const newScopeValues = upgradeReplaceViewProp(
|
|
102
|
+
'spatial', componentDef.props.view, coordinationSpace,
|
|
103
|
+
);
|
|
104
|
+
newComponentDef = {
|
|
105
|
+
...newComponentDef,
|
|
106
|
+
coordinationScopes: {
|
|
107
|
+
...newComponentDef.coordinationScopes,
|
|
108
|
+
...newScopeValues,
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
layout.push(newComponentDef);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const lcDef = layout.find(c => c.component === 'layerController');
|
|
117
|
+
const spatialDef = layout.find(c => c.component === 'spatial');
|
|
118
|
+
if (lcDef && spatialDef.coordinationScopes) {
|
|
119
|
+
lcDef.coordinationScopes = spatialDef.coordinationScopes;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Use a random dataset ID when initializing automatically,
|
|
123
|
+
// so that it changes with each new v0.1.0 view config.
|
|
124
|
+
// However, check if the `datasetUid` parameter was passed,
|
|
125
|
+
// which allows for unit testing.
|
|
126
|
+
const newDatasetUid = datasetUid || uuidv4();
|
|
127
|
+
|
|
128
|
+
return {
|
|
129
|
+
version: '1.0.1',
|
|
130
|
+
name: config.name,
|
|
131
|
+
description: config.description,
|
|
132
|
+
public: config.public,
|
|
133
|
+
datasets: [
|
|
134
|
+
{
|
|
135
|
+
uid: newDatasetUid,
|
|
136
|
+
name: newDatasetUid,
|
|
137
|
+
files: config.layers.map(layer => ({
|
|
138
|
+
type: layer.type.toLowerCase(),
|
|
139
|
+
fileType: layer.fileType,
|
|
140
|
+
url: layer.url,
|
|
141
|
+
})),
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
initStrategy: 'auto',
|
|
145
|
+
coordinationSpace,
|
|
146
|
+
layout,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export function upgradeFrom1_0_0(config) {
|
|
151
|
+
const newConfig = cloneDeep(config);
|
|
152
|
+
const { coordinationSpace } = newConfig;
|
|
153
|
+
|
|
154
|
+
function replaceLayerType(layerType) {
|
|
155
|
+
// Layer type could be one of a few things, bitmask or raster at the moment.
|
|
156
|
+
const isRaster = layerType === 'raster';
|
|
157
|
+
coordinationSpace[`spatial${capitalize(layerType)}Layer${isRaster ? 's' : ''}`] = {};
|
|
158
|
+
Object.entries(coordinationSpace.spatialLayers).forEach(([scope, layers]) => {
|
|
159
|
+
if (Array.isArray(layers) && layers.find(layer => layer.type === layerType)) {
|
|
160
|
+
const typedLayers = layers
|
|
161
|
+
.filter(layer => layer.type === layerType)
|
|
162
|
+
.map((layer) => {
|
|
163
|
+
const newLayer = { ...layer };
|
|
164
|
+
delete newLayer.type;
|
|
165
|
+
return newLayer;
|
|
166
|
+
});
|
|
167
|
+
coordinationSpace[`spatial${capitalize(layerType)}Layer${isRaster ? 's' : ''}`][scope] = isRaster ? typedLayers : typedLayers[0];
|
|
168
|
+
} else {
|
|
169
|
+
coordinationSpace[`spatial${capitalize(layerType)}Layer${isRaster ? 's' : ''}`][scope] = null;
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (coordinationSpace.spatialLayers) {
|
|
175
|
+
replaceLayerType('raster');
|
|
176
|
+
replaceLayerType('cells');
|
|
177
|
+
replaceLayerType('molecules');
|
|
178
|
+
replaceLayerType('neighborhoods');
|
|
179
|
+
delete coordinationSpace.spatialLayers;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const layout = newConfig.layout.map((component) => {
|
|
183
|
+
const newComponent = { ...component };
|
|
184
|
+
|
|
185
|
+
function replaceCoordinationScope(layerType) {
|
|
186
|
+
const isRaster = layerType === 'raster';
|
|
187
|
+
if (
|
|
188
|
+
['spatial', 'layerController'].includes(newComponent.component)
|
|
189
|
+
|| (newComponent.component === 'description' && isRaster)
|
|
190
|
+
) {
|
|
191
|
+
newComponent.coordinationScopes[`spatial${capitalize(layerType)}Layer${isRaster ? 's' : ''}`] = newComponent
|
|
192
|
+
.coordinationScopes.spatialLayers;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (newComponent.coordinationScopes && newComponent.coordinationScopes.spatialLayers) {
|
|
197
|
+
replaceCoordinationScope('raster');
|
|
198
|
+
replaceCoordinationScope('cells');
|
|
199
|
+
replaceCoordinationScope('molecules');
|
|
200
|
+
replaceCoordinationScope('neighborhoods');
|
|
201
|
+
delete newComponent.coordinationScopes.spatialLayers;
|
|
202
|
+
}
|
|
203
|
+
return newComponent;
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
return {
|
|
207
|
+
...newConfig,
|
|
208
|
+
coordinationSpace,
|
|
209
|
+
layout,
|
|
210
|
+
version: '1.0.1',
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
export function upgradeFrom1_0_1(config) {
|
|
216
|
+
// Need to add the globalDisable3d prop to any layer controller views,
|
|
217
|
+
// to match the previous lack of 3D auto-detection behavior.
|
|
218
|
+
|
|
219
|
+
const layout = config.layout.map((component) => {
|
|
220
|
+
const newComponent = { ...component };
|
|
221
|
+
if (newComponent.component === 'layerController') {
|
|
222
|
+
newComponent.props = {
|
|
223
|
+
...newComponent.props,
|
|
224
|
+
globalDisable3d: true,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
return newComponent;
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// Enforce bitmask or raster as spatial raster layer type, defaulting
|
|
231
|
+
// to raster layer if it is not one of bitmask or raster from the old config.
|
|
232
|
+
|
|
233
|
+
const newConfig = cloneDeep(config);
|
|
234
|
+
Object.keys((newConfig?.coordinationSpace?.spatialRasterLayers || {})).forEach((key) => {
|
|
235
|
+
if (newConfig.coordinationSpace.spatialRasterLayers[key]) {
|
|
236
|
+
newConfig.coordinationSpace.spatialRasterLayers[key].forEach((layer, index) => {
|
|
237
|
+
newConfig.coordinationSpace.spatialRasterLayers[key][index].type = ['bitmask', 'raster'].includes(layer.type) ? layer.type : 'raster';
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
return {
|
|
243
|
+
...newConfig,
|
|
244
|
+
layout,
|
|
245
|
+
version: '1.0.2',
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export function upgradeFrom1_0_2(config) {
|
|
250
|
+
// Need to add the globalDisable3d prop to any layer controller views,
|
|
251
|
+
// to match the previous lack of 3D auto-detection behavior.
|
|
252
|
+
|
|
253
|
+
const layout = config.layout.map((component) => {
|
|
254
|
+
const newComponent = { ...component };
|
|
255
|
+
if (newComponent.component === 'layerController') {
|
|
256
|
+
newComponent.props = {
|
|
257
|
+
...newComponent.props,
|
|
258
|
+
disableChannelsIfRgbDetected: true,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
return newComponent;
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
// Enforce bitmask or raster as spatial raster layer type, defaulting
|
|
265
|
+
// to raster layer if it is not one of bitmask or raster from the old config.
|
|
266
|
+
|
|
267
|
+
const newConfig = cloneDeep(config);
|
|
268
|
+
|
|
269
|
+
return {
|
|
270
|
+
...newConfig,
|
|
271
|
+
layout,
|
|
272
|
+
version: '1.0.3',
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
export function upgradeFrom1_0_3(config) {
|
|
277
|
+
const newConfig = cloneDeep(config);
|
|
278
|
+
|
|
279
|
+
return {
|
|
280
|
+
...newConfig,
|
|
281
|
+
version: '1.0.4',
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Added in version 1.0.5:
|
|
286
|
+
// - Support for an array of strings in the setName property within options array items
|
|
287
|
+
// for the anndata-cell-sets.zarr file type.
|
|
288
|
+
export function upgradeFrom1_0_4(config) {
|
|
289
|
+
const newConfig = cloneDeep(config);
|
|
290
|
+
|
|
291
|
+
return {
|
|
292
|
+
...newConfig,
|
|
293
|
+
version: '1.0.5',
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
// Added in version 1.0.6:
|
|
299
|
+
// - Support for the scoreName property within options array items
|
|
300
|
+
// for the anndata-cell-sets.zarr file type.
|
|
301
|
+
export function upgradeFrom1_0_5(config) {
|
|
302
|
+
const newConfig = cloneDeep(config);
|
|
303
|
+
|
|
304
|
+
return {
|
|
305
|
+
...newConfig,
|
|
306
|
+
version: '1.0.6',
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Added in version 1.0.7:
|
|
311
|
+
// - Support for aliasing the gene identifiers using a different var dataframe column
|
|
312
|
+
// via a new `geneAlias` option for the `anndata-expression-matrix.zarr` fileType.
|
|
313
|
+
export function upgradeFrom1_0_6(config) {
|
|
314
|
+
const newConfig = cloneDeep(config);
|
|
315
|
+
|
|
316
|
+
return {
|
|
317
|
+
...newConfig,
|
|
318
|
+
version: '1.0.7',
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Added in version 1.0.8:
|
|
323
|
+
// - Support for multiple `dataset` coordination scopes and
|
|
324
|
+
// dataset-specific coordination scope mappings for all
|
|
325
|
+
// other coordination types.
|
|
326
|
+
export function upgradeFrom1_0_7(config) {
|
|
327
|
+
const newConfig = cloneDeep(config);
|
|
328
|
+
|
|
329
|
+
return {
|
|
330
|
+
...newConfig,
|
|
331
|
+
version: '1.0.8',
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// Added in version 1.0.9:
|
|
336
|
+
// - Support for plugin coordination types.
|
|
337
|
+
export function upgradeFrom1_0_8(config) {
|
|
338
|
+
const newConfig = cloneDeep(config);
|
|
339
|
+
|
|
340
|
+
return {
|
|
341
|
+
...newConfig,
|
|
342
|
+
version: '1.0.9',
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// Added in version 1.0.10:
|
|
347
|
+
// - Support for the optional 'uid' property for views.
|
|
348
|
+
export function upgradeFrom1_0_9(config) {
|
|
349
|
+
const newConfig = cloneDeep(config);
|
|
350
|
+
|
|
351
|
+
return {
|
|
352
|
+
...newConfig,
|
|
353
|
+
version: '1.0.10',
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// Added in version 1.0.11:
|
|
358
|
+
// - Changes to spatial layer coordination type names.
|
|
359
|
+
// - Cell -> Obs, Gene -> Feature in coordination type names.
|
|
360
|
+
export function upgradeFrom1_0_10(config) {
|
|
361
|
+
const coordinationSpace = { ...config.coordinationSpace };
|
|
362
|
+
|
|
363
|
+
const scopeAnalogies = {
|
|
364
|
+
// Spatial layer types
|
|
365
|
+
spatialRasterLayers: 'spatialImageLayer',
|
|
366
|
+
spatialCellsLayer: 'spatialSegmentationLayer',
|
|
367
|
+
spatialMoleculesLayer: 'spatialPointLayer',
|
|
368
|
+
spatialNeighborhoodsLayer: 'spatialNeighborhoodLayer',
|
|
369
|
+
// Other types
|
|
370
|
+
cellFilter: 'obsFilter',
|
|
371
|
+
cellHighlight: 'obsHighlight',
|
|
372
|
+
cellSelection: 'obsSelection',
|
|
373
|
+
cellSetSelection: 'obsSetSelection',
|
|
374
|
+
cellSetHighlight: 'obsSetHighlight',
|
|
375
|
+
cellSetColor: 'obsSetColor',
|
|
376
|
+
geneFilter: 'featureFilter',
|
|
377
|
+
geneHighlight: 'featureHighlight',
|
|
378
|
+
geneSelection: 'featureSelection',
|
|
379
|
+
geneExpressionColormap: 'featureValueColormap',
|
|
380
|
+
geneExpressionColormapRange: 'featureValueColormapRange',
|
|
381
|
+
cellColorEncoding: 'obsColorEncoding',
|
|
382
|
+
additionalCellSets: 'additionalObsSets',
|
|
383
|
+
embeddingCellSetPolygonsVisible: 'embeddingObsSetPolygonsVisible',
|
|
384
|
+
embeddingCellSetLabelsVisible: 'embeddingObsSetLabelsVisible',
|
|
385
|
+
embeddingCellSetLabelSize: 'embeddingObsSetLabelSize',
|
|
386
|
+
embeddingCellRadius: 'embeddingObsRadius',
|
|
387
|
+
embeddingCellRadiusMode: 'embeddingObsRadiusMode',
|
|
388
|
+
embeddingCellOpacity: 'embeddingObsOpacity',
|
|
389
|
+
embeddingCellOpacityMode: 'embeddingObsOpacityMode',
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
Object.entries(scopeAnalogies).forEach(([oldKey, newKey]) => {
|
|
393
|
+
if (coordinationSpace[oldKey]) {
|
|
394
|
+
coordinationSpace[newKey] = coordinationSpace[oldKey];
|
|
395
|
+
delete coordinationSpace[oldKey];
|
|
396
|
+
}
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
const layout = config.layout.map((component) => {
|
|
400
|
+
const newComponent = { ...component };
|
|
401
|
+
const { coordinationScopes = {} } = newComponent;
|
|
402
|
+
|
|
403
|
+
Object.entries(scopeAnalogies).forEach(([oldKey, newKey]) => {
|
|
404
|
+
if (coordinationScopes[oldKey]) {
|
|
405
|
+
coordinationScopes[newKey] = coordinationScopes[oldKey];
|
|
406
|
+
delete coordinationScopes[oldKey];
|
|
407
|
+
}
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
return {
|
|
411
|
+
...newComponent,
|
|
412
|
+
coordinationScopes,
|
|
413
|
+
};
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
return {
|
|
417
|
+
...config,
|
|
418
|
+
coordinationSpace,
|
|
419
|
+
layout,
|
|
420
|
+
version: '1.0.11',
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// Added in version 1.0.12:
|
|
425
|
+
// - Added a fileType-to-dataType mapping
|
|
426
|
+
// so that datasets[].files[].type is no longer required.
|
|
427
|
+
export function upgradeFrom1_0_11(config) {
|
|
428
|
+
const newConfig = cloneDeep(config);
|
|
429
|
+
|
|
430
|
+
const {
|
|
431
|
+
datasets,
|
|
432
|
+
coordinationSpace,
|
|
433
|
+
} = newConfig;
|
|
434
|
+
|
|
435
|
+
if (coordinationSpace.embeddingType) {
|
|
436
|
+
// This array may contain more embedding types than
|
|
437
|
+
// the cells.json file actually contains, but the tradeoff is that
|
|
438
|
+
// we do not have to load the cells.json file to double check what
|
|
439
|
+
// embedding types are actually present. CellsJsonAsObsEmbedding
|
|
440
|
+
// will just load the embedding as null if it is not present.
|
|
441
|
+
const embeddingTypes = Object.values(coordinationSpace.embeddingType);
|
|
442
|
+
datasets.forEach((dataset, i) => {
|
|
443
|
+
const { files } = dataset;
|
|
444
|
+
files.forEach((fileDef, j) => {
|
|
445
|
+
const { fileType } = fileDef;
|
|
446
|
+
if (fileType === 'cells.json') {
|
|
447
|
+
datasets[i].files[j].options = {
|
|
448
|
+
embeddingTypes,
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
return {
|
|
456
|
+
...newConfig,
|
|
457
|
+
datasets,
|
|
458
|
+
version: '1.0.12',
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
// Added in version 1.0.13:
|
|
463
|
+
// - Adds the property `coordinationValues` for
|
|
464
|
+
// view config file definitions but is not yet
|
|
465
|
+
// used to do file matching/lookups.
|
|
466
|
+
export function upgradeFrom1_0_12(config) {
|
|
467
|
+
const newConfig = cloneDeep(config);
|
|
468
|
+
|
|
469
|
+
// Set up coordination scopes for anndata-cells.zarr's options.factors
|
|
470
|
+
// in the coordination space, and create a new coordinationScopes.obsLabelsType array
|
|
471
|
+
// for each component in the layout.
|
|
472
|
+
const { datasets, coordinationSpace, layout } = newConfig;
|
|
473
|
+
const datasetUidToObsLabelsTypeScopes = {};
|
|
474
|
+
datasets.forEach((dataset) => {
|
|
475
|
+
const { files, uid } = dataset;
|
|
476
|
+
files.forEach((fileDef) => {
|
|
477
|
+
const { fileType, options = {} } = fileDef;
|
|
478
|
+
if (fileType === 'anndata-cells.zarr') {
|
|
479
|
+
const { factors } = options;
|
|
480
|
+
if (factors) {
|
|
481
|
+
const obsLabelsTypeScopes = [];
|
|
482
|
+
factors.forEach((olt) => {
|
|
483
|
+
const nextScope = getNextScope(Object.keys(coordinationSpace?.obsLabelsType || {}));
|
|
484
|
+
coordinationSpace.obsLabelsType = {
|
|
485
|
+
...coordinationSpace.obsLabelsType,
|
|
486
|
+
// Need to remove the obs/ prefix.
|
|
487
|
+
[nextScope]: olt.split('/').at(-1),
|
|
488
|
+
};
|
|
489
|
+
obsLabelsTypeScopes.push(nextScope);
|
|
490
|
+
});
|
|
491
|
+
datasetUidToObsLabelsTypeScopes[uid] = obsLabelsTypeScopes;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
});
|
|
495
|
+
});
|
|
496
|
+
function getDatasetUidForView(viewDef) {
|
|
497
|
+
if (viewDef.coordinationScopes?.dataset) {
|
|
498
|
+
return coordinationSpace.dataset[viewDef.coordinationScopes.dataset];
|
|
499
|
+
}
|
|
500
|
+
if (datasets.length > 0) {
|
|
501
|
+
return datasets[0].uid;
|
|
502
|
+
}
|
|
503
|
+
return null;
|
|
504
|
+
}
|
|
505
|
+
const newLayout = layout.map((viewDef) => {
|
|
506
|
+
const viewDatasetUid = getDatasetUidForView(datasets, coordinationSpace, viewDef);
|
|
507
|
+
const datasetObsLabelsTypeScopes = datasetUidToObsLabelsTypeScopes[viewDatasetUid];
|
|
508
|
+
if (datasetObsLabelsTypeScopes) {
|
|
509
|
+
return {
|
|
510
|
+
...viewDef,
|
|
511
|
+
coordinationScopes: {
|
|
512
|
+
...viewDef.coordinationScopes,
|
|
513
|
+
obsLabelsType: datasetObsLabelsTypeScopes,
|
|
514
|
+
},
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
return viewDef;
|
|
518
|
+
});
|
|
519
|
+
|
|
520
|
+
return {
|
|
521
|
+
...newConfig,
|
|
522
|
+
coordinationSpace,
|
|
523
|
+
layout: newLayout,
|
|
524
|
+
version: '1.0.13',
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
// Added in version 1.0.14:
|
|
529
|
+
// - Adds the coordination types
|
|
530
|
+
// gatingFeatureSelectionX,
|
|
531
|
+
// gatingFeatureSelectionY,
|
|
532
|
+
// featureValueTransformCoefficient.
|
|
533
|
+
export function upgradeFrom1_0_13(config) {
|
|
534
|
+
const newConfig = cloneDeep(config);
|
|
535
|
+
|
|
536
|
+
return {
|
|
537
|
+
...newConfig,
|
|
538
|
+
version: '1.0.14',
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
// Added in version 1.0.15:
|
|
543
|
+
// - Changes the following view names:
|
|
544
|
+
// - genes -> featureList
|
|
545
|
+
// - cellSets -> obsSets
|
|
546
|
+
// - cellSetSizes -> obsSetSizes
|
|
547
|
+
// - cellSetExpression -> obsSetFeatureValueDistribution
|
|
548
|
+
// - expressionHistogram -> featureValueHistogram
|
|
549
|
+
// - Deprecates the props:
|
|
550
|
+
// - variablesLabelOverride
|
|
551
|
+
// - observationsLabelOverride
|
|
552
|
+
export function upgradeFrom1_0_14(config) {
|
|
553
|
+
const newConfig = cloneDeep(config);
|
|
554
|
+
const { layout } = newConfig;
|
|
555
|
+
|
|
556
|
+
const viewTypeAnalogies = {
|
|
557
|
+
genes: 'featureList',
|
|
558
|
+
cellSets: 'obsSets',
|
|
559
|
+
cellSetSizes: 'obsSetSizes',
|
|
560
|
+
cellSetExpression: 'obsSetFeatureValueDistribution',
|
|
561
|
+
expressionHistogram: 'featureValueHistogram',
|
|
562
|
+
};
|
|
563
|
+
// Handle the view type renaming.
|
|
564
|
+
const newLayout = layout.map((viewDef) => {
|
|
565
|
+
// Replace the old component name with the new one.
|
|
566
|
+
if (viewTypeAnalogies[viewDef.component]) {
|
|
567
|
+
return {
|
|
568
|
+
...viewDef,
|
|
569
|
+
component: viewTypeAnalogies[viewDef.component],
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
return viewDef;
|
|
573
|
+
});
|
|
574
|
+
const propAnalogies = {
|
|
575
|
+
variablesLabelOverride: 'featureType',
|
|
576
|
+
observationsLabelOverride: 'obsType',
|
|
577
|
+
};
|
|
578
|
+
// Warn about the prop usage.
|
|
579
|
+
newLayout.forEach((viewDef) => {
|
|
580
|
+
// Iterate over each old prop key.
|
|
581
|
+
Object.entries(propAnalogies).forEach(([oldProp, newType]) => {
|
|
582
|
+
if (viewDef.props?.[oldProp]) {
|
|
583
|
+
console.warn(`Warning: the '${oldProp}' prop on the ${viewDef.component} view is deprecated. Please use the '${newType}' coordination type instead.`);
|
|
584
|
+
}
|
|
585
|
+
});
|
|
586
|
+
});
|
|
587
|
+
return {
|
|
588
|
+
...newConfig,
|
|
589
|
+
version: '1.0.15',
|
|
590
|
+
layout: newLayout,
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// Added in version 1.0.16:
|
|
595
|
+
// - Explict coordinationScopesBy property for view definitions,
|
|
596
|
+
// to replace the previous implicit mapping of per-dataset coordination
|
|
597
|
+
// scopes.
|
|
598
|
+
export function upgradeFrom1_0_15(config) {
|
|
599
|
+
const newConfig = cloneDeep(config);
|
|
600
|
+
|
|
601
|
+
const { layout } = newConfig;
|
|
602
|
+
const newLayout = layout.map((view) => {
|
|
603
|
+
const { coordinationScopes = {} } = view;
|
|
604
|
+
if (coordinationScopes.dataset && Array.isArray(coordinationScopes.dataset)) {
|
|
605
|
+
const coordinationScopesBy = {
|
|
606
|
+
dataset: {},
|
|
607
|
+
};
|
|
608
|
+
Object.entries(coordinationScopes).forEach(([coordinationType, coordinationScope]) => {
|
|
609
|
+
if (coordinationType !== 'dataset' && !Array.isArray(coordinationScope) && typeof coordinationScope === 'object') {
|
|
610
|
+
coordinationScopesBy.dataset[coordinationType] = coordinationScope;
|
|
611
|
+
delete coordinationScopes[coordinationType];
|
|
612
|
+
}
|
|
613
|
+
});
|
|
614
|
+
return {
|
|
615
|
+
...view,
|
|
616
|
+
coordinationScopes,
|
|
617
|
+
coordinationScopesBy,
|
|
618
|
+
};
|
|
619
|
+
}
|
|
620
|
+
return view;
|
|
621
|
+
});
|
|
622
|
+
|
|
623
|
+
return {
|
|
624
|
+
...newConfig,
|
|
625
|
+
layout: newLayout,
|
|
626
|
+
version: '1.0.16',
|
|
627
|
+
};
|
|
628
|
+
}
|